# Руководство FreeBSD по созданию портов

### The FreeBSD Documentation Project

Copyright © 2000, 2001, 2002, 2003, 2004 The FreeBSD Documentation Project

FreeBSD это зарегистрированная торговая марка The FreeBSD Foundation.

UNIX это зарегистрированная торговая марка The Open Group в США и других странах.

Sun, Sun Microsystems, SunOS, Solaris, и Java это торговые марки или зарегистрированные торговые марки Sun Microsystems, Inc. в Соединенных Штатах и других странах.

Apple и QuickTime это торговые марки Apple Computer, Inc., зарегистрированные в США и других странах.

Macromedia и Flash это торговые марки или зарегистрированные торговые марки Macromedia, Inc. в Соединенных Штатах и/или других странах.

Microsoft, Windows, и Windows Media это или зарегистрированные торговые марки или торговые марки Microsoft Corporation в Соединенных Штатах и/или других странах.

PartitionMagic это зарегистрированная торговая марка PowerQuest Corporation в Соединенных Штатах и/или других странах.

Многие из обозначений, используемых производителями и продавцами для обозначения своих продуктов, заявляются как торговые марки. Когда такие обозначения появляются в этой книге, и Проекту FreeBSD известно о торговой марке, к обозначению добавляется знак '™'.

Распространение и использование исходных (SGML DocBook) и ``скомпилированных'' форм (SGML, HTML, PDF, PostScript, RTF и прочих) с модификацией или без оной, разрешены при соблюдении следующих соглашений:

1. Распространяемые копии исходного кода (SGML DocBook) должны сохранять вышеупомянутые объявления copyright, этот список положений и следующий отказ от ответственности в первых строках этого файла в неизменном виде.

2. Распространяемые копии скомпилированных форм (преобразованные в другие DTD, конвертированные в PDF, PostScript, RTF и другие форматы) должны повторять вышеупомянутые объявления copyright, этот список положений и следующий отказ от ответственности в документации и/или других материалах, поставляемых с дистрибьюцией.

> Важно: ЭТА ДОКУМЕНТАЦИЯ ПОСТАВЛЯЕТСЯ ПРОЕКТОМ ДОКУМЕНТАЦИИ FREEBSD "КАК ЕСТЬ" И ЛЮБЫЕ ЯВНЫЕ ИЛИ НЕЯВНЫЕ ГАРАНТИИ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ НЕЯВНЫМИ ГАРАНТИЯМИ, КОММЕРЧЕСКОЙ ЦЕННОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ ОТРИЦАЮТСЯ. НИ ПРИ КАКИХ УСЛОВИЯХ ПРОЕКТ ДОКУМЕНТИРОВАНИЯ FREEBSD НЕ НЕСЕТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБОЙ ПРЯМОЙ, КОСВЕННЫЙ, СЛУЧАЙНЫЙ, СПЕЦИАЛЬНЫЙ, ОБРАЗЦОВЫЙ ИЛИ ПОСЛЕДУЮЩИЙ УЩЕРБЫ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ПОСТАВКОЙ ТОВАРОВ ЗАМЕНЫ ИЛИ УСЛУГ; ПОТЕРЮ ДАННЫХ ИЛИ ИХ НЕПРАВИЛЬНУЮ ПЕРЕДАЧУ ИЛИ ПОТЕРИ; ПРИОСТАНОВЛЕНИЕ БИЗНЕСА), И ТЕМ НЕ МЕНЕЕ ВЫЗВАННЫЕ И В ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ, НЕЗАВИСИМО ОТ КОНТРАКТНОЙ, СТРОГОЙ ОТВЕТСТВЕННОСТИ, ИЛИ ПРАВОНАРУШЕНИИ (ВКЛЮЧАЯ ХАЛАТНОСТЬ ИЛИ ИНЫМ СПОСОБОМ), ВОЗНИКШЕМ ЛЮБЫМ ПУТЕМ ПРИ ИСПОЛЬЗОВАНИИ ЭТОЙ ДОКУМЕНТАЦИИ, ДАЖЕ ЕСЛИ БЫ БЫЛО СООБЩЕНО О ВОЗМОЖНОСТИ ТАКОГО УЩЕРБА.

[ По разделам / Одним файлом ]

Список таблиц
5-1. Переменные `USE_`*``
6-1. Переменные для портов, использующих `perl`
6-2. Переменные для портов, использующих X
6-3. Переменные для портов, использующих automake, autoconf или libtool
6-4. Переменные для портов, которые используют KDE
6-5. Переменные, которые которые могут задаваться портами, использующими Java
6-6. Переменные, доступные в портах, использующих Java
6-7. Константы, определённые для портов, использующих Java
16-1. Значения __FreeBSD_version

Список примеров
5-1. Упрощённое использование `MASTER_SITES:n` с 1 файлом на каждом сайте
5-2. Упрощённое использование `MASTER_SITES:n` с более чем 1 файлом на каждом сервере
5-3. Подробное использование `MASTER_SITES:n` в `MASTER_SITE_SUBDIR`
5-4. Подробное использование `MASTER_SITES:n` с запятыми, несколькими файлами, несколькими серверами и несколькими подкаталогами
5-5. Подробное использование `MASTER_SITES:n` с `MASTER_SITE_SOURCEFORGE`
5-6. Упрощённое использование `MASTER_SITES:n` с `PATCH_SITES`.
14-1. Как избегать использование `.error`

# Глава 1. Введение

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

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

# Глава 2. Как самому сделать порт

Итак, вы интересуетесь, как создать собственный порт или обновить существующий? Великолепно!

Ниже находятся некоторые указания по созданию нового порта для FreeBSD. Если вы хотите обновить существующий порт, вы должны прочесть их, а затем Гл. 15.

Если этот документ недостаточно подробен, вы должны обратиться к файлу `/usr/ports/Mk/bsd.port.mk`, который включается в make-файл каждого порта. Он хорошо прокомментирован, и даже если вы не занимаетесь хаканьем make-файлов каждодневно, из него вы сможете узнать много нового. Кроме того, конкретные вопросы можно задать, послав письмо на адрес Список рассылки, посвящённый Портам FreeBSD.

> Замечание: Только часть переменных (``VAR``), которые могут быть переопределены, описаны в этом документе. Большинство (если не все) описаны в начале файла `/usr/ports/Mk/bsd.port.mk`; остальные, скорее всего, тоже там описаны. Заметьте, что в этом файле используется нестандартная настройка шага табуляции: Emacs и Vim должны распознать это при загрузке файла. Как vi(1), так и ex(1) могут быть настроены на использование правильного значения выдачей команды `:set tabstop=4` после загрузки файла.

# Глава 3. Быстрое портирование

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

Во-первых, скачайте оригинальный tar-файл и поместите его в каталог `DISTDIR`, который по умолчанию есть не что иное, как `/usr/ports/distfiles`.

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

## 3.1. Создание файла `Makefile`

Минимальный `Makefile` будет выглядеть примерно так:

    # New ports collection makefile for:   oneko
    # Date created:        5 December 1994
    # Whom:            asami
    #
    # $FreeBSD$
    #

    PORTNAME=      oneko
    PORTVERSION=   1.1b
    CATEGORIES=    games
    MASTER_SITES=  ftp://ftp.cs.columbia.edu/archives/X11R5/contrib/

    MAINTAINER=    asami@FreeBSD.org

    MAN1=          oneko.1
    MANCOMPRESSED= yes
    USE_IMAKE=     yes

    .include <bsd.port.mk>

Посмотрим, сможете ли вы его понять. Не обращайте внимание на содержимое строчки `$FreeBSD$`, она будет заполнена автоматически системой CVS, когда порт будет импортирован в наше дерево портов. Вы можете найти более подробный пример в разделе пример Makefile.

## 3.2. Создание информационных файлов

Имеется два информационных файла, которые требуются для любого порта, вне зависимости от того, является ли он пакетом или нет. Это `pkg-descr` и `pkg-plist`. Префикс `pkg-` отличает их от других файлов.

### 3.2.1. `pkg-descr`

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

> Замечание: Это не руководство и не подробнейшее описание того, как использовать или компилировать порт! Пожалуйста, будьте внимательны при копировании текста из `README` или страниц справочника; слишком часто они не являются кратким описанием порта или имеют неудобный формат (например, страницы справочника выровнены пробелами). Если портируемое приложение имеет официальную страничку Интернет, укажите ее здесь. Перед одним из сайтов добавьте слово `WWW:` для того, чтобы вспомогательные утилиты работали правильно.

Рекомендуется, чтобы вы указали свое имя в конце этого файла, как здесь:

    This is a port of oneko, in which a cat chases a poor mouse all over
    the screen.
     :
    (etc.)

    WWW: http://www.oneko.org/

    - Satoshi
    asami@cs.berkeley.edu

### 3.2.2. `pkg-plist`

Здесь перечисляются все файлы, устанавливаемые портом. Его также называют ``списком для упаковки'', потому что пакет генерируется упаковкой файлов, которые здесь указаны. Имена путей указываются относительно установочного префикса (обычно `/usr/local` или `/usr/X11R6`). Если вы используете переменные `MAN`n`` (а вы должны это делать), то указывать страницы справочника здесь не нужно.

Вот маленький пример:

    bin/oneko
    lib/X11/app-defaults/Oneko
    lib/X11/oneko/cat1.xpm
    lib/X11/oneko/cat2.xpm
    lib/X11/oneko/mouse.xpm
    @dirrm lib/X11/oneko

Обратитесь к странице справочной системы по команде pkg_create(1) с подробным описанием формата списка упаковки.

> Замечание: В списке вы должны указать все файлы, но не каталоги. Кроме того, если порт создает каталоги сам на этапе установки, нужно добавить директивы `@dirrm` в подходящие места для удаления их при удалении порта.

> Рекомендуется, чтобы имена файлов в этом списке были отсортированы в алфавитном порядке. Это позволит значительно облегчить сверку изменений при обновлении порта.

> Создание списка упаковки вручную может оказаться весьма трудоёмкой задачей. Если порт устанавливает большое количество файлов, раздел об автоматическом построении списка упаковки может помочь сэкономить время.

Существует только одно исключение, когда у порта может отсутствовать `pkg-plist`. Если порт устанавливает лишь несколько файлов, а возможно, и каталогов, то они могут быть перечислены в переменных `PLIST_FILES` и `PLIST_DIRS`, соответственно, внутри файла `Makefile` порта. К примеру, мы можем обойтись без файла `pkg-plist` у приведённого выше порта `oneko`, добавив следующие строки в `Makefile`:

    PLIST_FILES=   bin/oneko \
            lib/X11/app-defaults/Oneko \
            lib/X11/oneko/cat1.xpm \
            lib/X11/oneko/cat2.xpm \
            lib/X11/oneko/mouse.xpm
    PLIST_DIRS= lib/X11/oneko

Конечно, переменная `PLIST_DIRS` не должна задаваться, если порт не устанавливает никаких каталогов.

Обратной стороной такого способа перечисления файлов и каталогов порта является невозможность использования последовательностей команд, описанных в pkg_create(1). Поэтому он подходит для простых портов, что делает их ещё более простыми. Одновременно с этим положительным моментом является уменьшение количества файлов в коллекции портов. Пожалуйста, подумайте над использованием этой техники, прежде чем создавать `pkg-plist`.

Далее мы увидим, как можно использовать файлы `pkg-plist` и `PLIST_FILES` выполнения более сложных задач.

## 3.3. Создание файла с контрольной суммой

Просто введите команду `make makesum`. Правила утилиты make автоматически сгенерируют файл `distinfo`.

## 3.4. Тестирование порта

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

- `pkg-plist` не содержит ничего сверх того, что устанавливается вашим портом

- `pkg-plist` содержит абсолютно все, что устанавливается вашим портом

- Ваш порт может быть переустановлен множество раз с помощью указания цели `reinstall`

- Ваш порт подчищает за собой после своего удаления

Рекомендуемый порядок проверки

1. `make install`

2. `make package`

3. `make deinstall`

4. `pkg_add `package-name``

5. `make deinstall`

6. `make reinstall`

7. `make package`

Проверьте, что ни на шаге `package`, ни на шаге `deinstall` не выдается никаких предупреждений. После выполнения шага 3 проверьте, что все новые каталоги были успешно удалены. Также попробуйте запустить программное обеспечение после выполнения шага 4, чтобы убедиться, что оно работает правильно при установке из пакета.

## 3.5. Проверка вашего порта утилитой `portlint`

Будьте добры, пользуйтесь утилитой `portlint` для проверки того, что ваш порт соответствует нашим рекомендациям. Программа `portlint` является частью Коллекции Портов. В частности, вы можете захотеть проверить, правильно ли сформирован файл Makefile и соответствующим ли образом наименован пакет.

## 3.6. Посылка порта

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

Теперь, когда вы счастливы от своего первого порта, единственное, что осталось сделать, это включить его в основное дерево портов FreeBSD и осчастливить этим всех остальных. Нам не нужен ни ваш каталог `work`, ни пакет `pkgname.tgz`, так что удалите их прямо сейчас. Затем просто включите вывод команды `shar `find port_dir`` в сообщение об ошибке и пошлите его с помощью программы send-pr(1) (обратитесь к разделу Сообщения об ошибках и общие замечания для получения подробной информации о программе send-pr(1)). Если размер неупакованного порта превышает 20КБ, то сожмите его в tar-файл и воспользуйтесь утилитой uuencode(1) перед тем, как включить его в сообщение (можно посылать такие файлы, даже если сообщение не превышают 20КБ, но это не рекомендуется). Не забудьте указать в сообщении категорию `ports` и класс `change-request` (Не указывайте, что сообщение имеет статус `confidential`!). Добавьте также краткое описание программы, порт которой вы создали, в раздел ``Description'' отправляемого PR и сам порт в виде архива shar или архива tar, обработанного утилитой uuencode, поместив его в раздел ``Fix''.

> Замечание: Вы можете значительно облегчить нашу работу, если в тему сообщения о проблеме поместите хорошее описание. Мы рекомендуем нечто вроде ``New port: <категория>/<название порта> <краткое описание порта>'' для новых портов и ``Update port: <категория>/<имя порта> <краткое описание обновления>'' в случае обновления портов. Если вы следуете этой схеме, то шансы на то, что на ваше PR вскоре кто-то взглянет, гораздо выше.

Повторим ещё раз, что не нужно включать ни оригинальный файл с дистрибутивом, ни каталог `work`, ни пакет, построенный вами командой `make package`.

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

Мы рассмотрим ваш порт, при необходимости вернём его обратно, а затем включим порт в наше дерево. Ваше имя также появится в списке Дополнительных контрибуторов проекта FreeBSD и других файлах. Разве это не великолепно?!? :-)

# Глава 4. Медленное портирование

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

## 4.1. Как всё это работает

Во-первых, когда пользователь дает в своем каталоге с портом команду `make`, происходит целая череда событий. Во время чтения этого текста может оказаться полезным иметь файл `bsd.port.mk` открытым в другом окне, что сильно поможет в их понимании.

Но не волнуйтесь сильно, если вы не до конца понимаете, что делается в `bsd.port.mk`, не так уж много людей его понимает... :->

1. Запускается цель `fetch`. Цель `fetch` отвечает за то, что архив исходных текстов имеется в наличии локально в каталоге `DISTDIR`. Если цель `fetch` не может найти требуемые файлы в каталоге `DISTDIR`, то он будет искаться по указателю URL `MASTER_SITES`, который устанавливается в Makefile, а также на нашем основном FTP-сервере по адресу ftp://ftp.FreeBSD.org/pub/FreeBSD/ports/distfiles/, куда мы по возможности помещаем дистрибутивные файлы для архива. Затем она попытается сгрузить указанный файл с помощью `FETCH`, полагая, что запрашивающая машина имеет прямое подключение к Интернет. Если файл скачается удачно, то он будет помещен в каталог `DISTDIR` для последующего использования и обработки.

2. Выполняется цель `extract`. Она ищет дистрибутивный файл порта (как правило, tar-архив gzip) в каталоге `DISTDIR` и распаковывает его во временный каталог, задаваемый переменной `WRKDIR` (по умолчанию `work`).

3. Выполняется цель `patch`. Во-первых, применяются все патчи, заданные переменной `PATCHFILES`. Во-вторых, если какие-либо файлы с патчами, носящие имена `patch-`*``, имеются в подкаталоге `PATCHDIR` (по умолчанию это каталог `files`), то они применяются в этот момент в алфавитном порядке.

4. Запускается цель `configure`. Здесь может выполняться любая из многих различных вещей.

   1. Если существует скрипт `scripts/configure`, то он запускается.

   2. Если задана переменная `HAS_CONFIGURE` или `GNU_CONFIGURE`, то запускается скрипт ``WRKSRC`/configure`.

   3. Если задана переменная `USE_IMAKE`, то запускается команда `XMKMF` (по умолчанию это `xmkmf -a`).

5. Выполняется цель `build`. Она отвечает за переход в собственный рабочий каталог порта (`WRKSRC`) и его построение. Если задана переменная `USE_GMAKE`, будет использоваться GNU-версия утилиты `make`, в противном случае будет использована системная утилита `make`.

Выше перечислены стандартные действия. Кроме того, вы сами можете определить цели `pre-`что-то`` или `post-`что-то``, или создать скрипты с такими именами в подкаталоге `scripts`, и они будут запущены до или после выполнения действий по умолчанию.

Например, если у вас есть цель `post-extract`, определённая в вашем файле `Makefile` и файл `pre-build` в подкаталоге `scripts`, то после выполнения обычных действий по распаковке, будет вызвана цель `post-extract` а скрипт `pre-build` будет выполнен перед запуском стандартных правил построения. Рекомендуется использовать цели из `Makefile`, если действия достаточно просты, потому что в дальнейшем будет проще определить, какие нестандартные действия требует порт.

Действия по умолчанию выполняются целями `do-`что-то`` из `bsd.port.mk`. Например, команды для распаковки порта находятся в цели `do-extract`. Если вам не хватает цели по умолчанию, вы можете ее исправить, переопределив цель `do-`something`` в вашем файле `Makefile`.

> Замечание: ``Основные'' цели (к примеру, `extract`, `configure` и так далее) не делают ничего больше, чем проверяют успешность завершения всех предыдущих шагов и вызывают настоящие цели или скрипты, и их не нужно менять. Если вам нужно изменить распаковку, исправляйте `do-extract`, но никогда не меняйте способ работы `extract`!

Теперь вы представляете, что происходит, когда пользователь набирает команду `make`, теперь давайте пройдемся через шаги, рекомендуемые для создания настоящего порта.

## 4.2. Получение исходного кода

Получите оригинальные исходные тексты (обычно) в виде упакованного tar-архива (``foo`.tar.gz` или ``foo`.tar.Z`) и скопируйте его в каталог `DISTDIR`. Всегда используйте исходные тексты основной ветки разработки везде, где это возможно.

Вам потребуется задать значение переменной `MASTER_SITES` так, чтобы оно указывало на местоположение оригинального tar-архива. В файле `bsd.sites.mk` вы найдёте краткие обозначения для большинства популярных сайтов. Пожалуйста, используйте эти сайты--и соответствующие определения--везде, где это возможно, чтобы избежать проблем повторения одной и той же информации в базе источников. Так как эти сайты со временем меняются, для всех причастных поддержка становится настоящим кошмаром.

Если вы не можете найти FTP/HTTP сайт с хорошим подключением к сети, или находите только сайты, которые имеют раздражающе нестандартные форматы, то можете захотеть поместить копию на надежный сервер FTP или HTTP, который вам доступен (например, ваша домашняя страница).

Если вы не можете найти доступного и надёжного места для помещения дистрибутивного файла, то мы сами сможем разместить его на сервере `ftp.FreeBSD.org`; однако это наименее рекомендуемое решение. Дистрибутивный файл должен быть помещён в каталог `~/public_distfiles/` одного из пользователей машины `freefall`. Попросите того, кто коммиттил ваш порт, сделать это. Этот человек также задаст переменной `MASTER_SITES` значение `MASTER_SITE_LOCAL`, а в переменной `MASTER_SITE_SUBDIR` укажет своё имя пользователя с машины `freefall`.

Если дистрибутивные файлы вашего порта постоянно меняются по неизвестным причинам без изменения версий со стороны автора, остаётся только поместить дистрибутив на вашу домашнюю Web-страницу и указать её первой в списке `MASTER_SITES`. Если можете, попытайтесь договориться с автором порта об этом; это действительно помогает в достижении некоторого управления исходным кодом. Хостирование собственной версии поможет избежать появления ошибок у пользователей типа “`checksum mismatch`”, а также уменьшит нагрузку на людей, сопровождающих наш FTP-сервер. Также, если у порта имеется только один основной сервер, то рекомендуется поместить архивную копию на свой сайт и указать его в списке `MASTER_SITES` вторым.

Если вашему порту требуются дополнительные `патчи', доступные в Интернет, скачайте также и их, поместив в каталог `DISTDIR`. Не волнуйтесь, если они находятся не на том же сайте, откуда взят дистрибутивный архив, мы умеем обрабатывать такие ситуации (смотрите описание PATCHFILES ниже).

## 4.3. Модификация порта

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

Если вашему порту во время компиляции, установки и настройки требуется довольно много взаимодействовать с пользователем, то посмотрите на один из классических скриптов Configure Лэрри Уолла (Larry Wall) и сделайте сами что-либо подобное. Предназначение новой коллекции портов - это сделать каждое приложение в стиле ``plug-and-play'' настолько, насколько это вообще возможно для конечного пользователя при минимальном использовании дискового пространства.

> Замечание: Если явно не указано обратное, то патчи, скрипты и другие файлы, которые вы создали и предоставили для Коллекции Портов FreeBSD, неявно подпадают под стандартные условия лицензии BSD.

## 4.4. Создание патчей

Файлы, которые добавлялись или изменялись в процессе создания порта, могут быть выявлены вызовом программы diff(1) с рекурсией, а результат работы этой программы может быть в дальнейшем передан программе patch(1). Каждый набор патчей, который вы собираетесь применить, должен быть собран в файл с именем `patch-`*``, где `*` означает порядок, в которой будут применяться патчи -- это делается в алфавитном порядке, то есть сначала `aa`, затем `ab` и так далее. Если хотите, вы можете использовать имена файлов, указывающие на имена файлов, к которым применяются патчи, такие, как `patch-Imakefile` или `patch-src-config.h`. Эти файлы должны находиться в каталоге `PATCHDIR`, откуда они будут взяты автоматически. Все патчи должны быть сделаны относительно каталога `WRKSRC` (как правило, это каталог, в который распаковывается исходный архив и где будет выполняться построение). Для упрощения внесения изменений и обновлений вы должны избегать наличия более чем одного патча для одного и того же файла (например, патчей `patch-aa` и `patch-ab`, оба меняющих файл ``WRKSRC`/foobar.c`).

Не помещайте строки RCS в патчи. CVS будет изменять их при помещении файлов в дерево портов, и когда мы будем их оттуда извлекать, они будут уже другие, поэтому применение патчей окончится неудачей. Строчки RCS предваряются знаком доллара (`$`), и обычно начинаются с `$Id` или `$RCS`.

Использование параметра рекурсии (`-r`) с командой diff(1) для генерации патчей - это хорошо, но всё же, пожалуйста, смотрите на получающиеся патчи, чтобы убедиться в отсутствии ненужного мусора. В частности, diff-разниц между двумя резервными копиями файлов, файлы `Makefile`, когда как порт использует `Imake` или GNU-версию программы `configure`, и так далее, не нужны, и должны быть удалены. Если вы отредактировали файл `configure.in` и запустили `autoconf` для перегенерации `configure`, не нужно включать файлы diff для `configure` (они частенько вырастают до нескольких тысяч строк!); задайте `USE_AUTOCONF_VER=213` и включите diff-файл для `configure.in`.

Кроме того, если вы удаляете файл, то это можно сделать и в цели `post-extract`, а не внутри патча. Как только вы будете удовлетворены получающимся diff-файлом, разбейте его на несколько по одному патчу на отдельный файл.

## 4.5. Конфигурирование

Поместите все дополнительные команды, требуемые для настройки, в ваш скрипт `configure` и сохраните его в подкаталоге `scripts`. Как отмечено выше, вы можете сделать это целями в файле `Makefile` и/или скриптами с именами `pre-configure` или `post-configure`.

## 4.6. Обработка пользовательского ввода

Если для построения, конфигурации или установки вашего порта требуется некоторый ввод со стороны пользователя, то вы должны задать переменную `IS_INTERACTIVE` в вашем файле `Makefile`. В случае ``ночного построения'' это позволит пропустить ваш порт, если пользователь в своем окружении задал переменную `BATCH` (и если пользователь установил переменную `INTERACTIVE`, то будут строиться только порты, которые требуют взаимодействия с пользователем. Это сэкономит значительное количество времени на части машин, которые постоянно строят порты (смотрите ниже).

При наличии разумных ответов на задаваемые вопросы, подходящих по умолчанию, также рекомендуется проверять переменную `PACKAGE_BUILDING` и выключать интерактивный скрипт, если он есть. Это позволит нам строить пакеты для помещения на компакт-диски и FTP-серверы.

# Глава 5. Настройка файла Makefile

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

Итак, расположим решаемые задачи в порядке их возникновения при создании вашего нового файла `Makefile`:

## 5.1. Оригинальные исходный код

Находится ли он в каталоге `DISTDIR` в виде стандартного упакованного архиватором gzip tar-архива с именем типа `foozolix-1.2.tar.gz`? Если это так, можно перейти к следующему шагу. Если нет, то вы должны попытаться переопределить некоторые из переменных `DISTNAME`, `EXTRACT_CMD`, `EXTRACT_BEFORE_ARGS`, `EXTRACT_AFTER_ARGS`, `EXTRACT_SUFX` или `DISTFILES` в зависимости от того, насколько необычен формат дистрибутивного файла. (Самый распространённый случай - это `EXTRACT_SUFX=.tar.Z`, когда tar-файл упакован обычной утилитой `compress`, а не архиватором `gzip`.)

В худшем случае вы можете просто определить свою собственную цель `do-extract` для переопределения действий по умолчанию, хотя к этому нужно будет прибегать в очень редких случаях, если вообще придётся.

## 5.2. Именование

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

### 5.2.1. `PORTNAME` и `PORTVERSION`

В переменной `PORTNAME` вы должны указать основную часть имени вашего порта, а в переменной `PORTVERSION` - номер версии.

### 5.2.2. `PORTREVISION` и `PORTEPOCH`

#### 5.2.2.1. `PORTREVISION`

Переменная `PORTREVISION` представляет собой монотонно увеличивающееся число, которое обнуляется при каждом увеличении значения переменной `PORTVERSION` (то есть каждый раз, когда создателями выпускается новый официальный релиз), и добавляется к имени пакета, если оно не равно нулю. Изменения в `PORTREVISION` используются автоматизированными инструментами (например, pkg_version(1)) для определения факта появления нового пакета.

Значение `PORTREVISION` должно увеличиваться каждый раз, когда в порте FreeBSD делаются изменения, которые достаточно сильно затрагивают содержимое или структуру соответствующего пакета.

Примеры случаев, когда значение `PORTREVISION` должно быть увеличено:

- Добавление патчей для исправления пробелов в безопасности, ошибок, или добавления новой функциональности в порт.

- Изменения в файле `Makefile` порта для включения и выключения параметров, определяемых при компиляции пакета.

- Изменения в списке упаковки или в поведении пакета во время его установки (например, изменение скрипта, генерирующего начальные данные для пакета, такие, как ssh-ключи для хоста).

- Увеличение версии динамической библиотеки, от которой зависит порт (в этом случае тот, кто попытается установить старый пакет после установки более новой версии библиотеки, не сможет этого сделать, потому что при этом будет делаться поиск старой библиотеки libfoo.x, а не libfoo.(x+1)).

- Большие функциональные изменения в дистрибутивном файле порта, происходящие без объявлений, и приводящие к большим изменениям, то есть изменения в дистрибутиве требуют корректировки файла `distinfo` без соответствующего изменения `PORTVERSION`, когда как команда `diff -ru` между новой и старой версиями показывает нетривиальные изменения в коде.

Примеры изменений, которые не требуют увеличения переменной `PORTREVISION`:

- Изменения стиля в скелете порта без функциональных изменений в пакете.

- Изменения в переменной `MASTER_SITES` или другие функциональные изменения порта, которые не затрагивают получающегося пакета.

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

- Исправления, касающиеся этапа построения, которые делают возможным построение пакета, если ранее это было невозможно сделать (пока изменения не приводят к изменению работы на любых других платформах, на которых порт ранее строился). Так как `PORTREVISION` отражает содержимое пакета, то, если ранее пакет не строился, то нет нужды увеличивать `PORTREVISION` для отметки изменения.

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

#### 5.2.2.2. `PORTEPOCH`

Время от времени разработчик программного обеспечения или создатель порта FreeBSD делают что-то не так и выпускают версию программы, номер которой меньше предыдущей версии. Примером этого является порт, название которого меняется с foo-20000801 на foo-1.0 (изначально это не считалось бы более новой версией, так как 20000801 численно больше, чем 1).

В ситуациях, подобных этой, должно быть увеличено значение `PORTEPOCH`. Если значение `PORTEPOCH` не равно нулю, то оно добавляется к имени пакета, как описано в разделе выше. Значение `PORTEPOCH` никогда не должно уменьшаться или сбрасываться в ноль, потому что это приведёт к ошибке сравнения с пакетом с меньшим номером эпохи (то есть то, что пакет устарел, обнаружено не будет): номер новой версии (например, `1.0,1` в примере выше) останется меньше, чем номер предыдущей версии (20000801), однако суффикс `,1` интерпретируется различными автоматизированными утилитами особым образом, и окажется больше, чем предполагаемый суффикс `,0` более раннего пакета).

Некорректное уменьшение или сброс `PORTEPOCH` приводит к печальным последствиям; если вы не поняли, о чём шла речь ранее, пожалуйста, всё же разберитесь с этим, либо спросите в списках рассылки.

Предполагается, что в большинстве портов переменная `PORTEPOCH` использоваться не будет, но при корректном использовании `PORTVERSION` может появиться необходимость её иметь, если в будущих релизах программное обеспечение должно изменить структуру номера версии. Однако создателям портов нужно быть внимательными, когда разработчик выпускает релиз без официального номера версии -- эдакие ``промежуточные'' релизы. Имеется соблазн пометить релиз датой его выхода, что может вызвать проблемы, как и в примере выше, когда будет выпущен новый ``официальный'' релиз.

Например, если промежуточный релиз помечен датой 20000917, а предыдущая версия программного обеспечения имела номер 1.2, то промежуточному релизу должно быть поставлено в соответствие значение `PORTVERSION`, равное 1.2.20000917 или что-то похожее, но не 20000917, так как последующий релиз, скажем, 1.3, должен иметь численно большее значение.

#### 5.2.2.3. Пример использования переменных `PORTREVISION` и `PORTEPOCH`

Выполнен коммит порта `gtkmumble`, версии `0.10`, в коллекцию портов.

    PORTNAME=      gtkmumble
    PORTVERSION=   0.10

Значение `PKGNAME` станет равным `gtkmumble-0.10`.

Обнаружен пробел в безопасности, что потребовало создания локального патча для FreeBSD. Соответственно было увеличено значение переменной `PORTREVISION`.

    PORTNAME=      gtkmumble
    PORTVERSION=   0.10
    PORTREVISION=  1

`PKGNAME` принимает значение `gtkmumble-0.10_1`

Разработчиком выпущена новая версия с номером `0.2` (оказалось, что под номером `0.10` автор имел в виду `0.1.0`, а не ``то, что будет выпущено после версии 0.9'' - извините, теперь уже поздно). Так как новый младший номер версии `2` по значению меньше, чем номер предыдущей версии `10`, то должно быть увеличено значение `PORTEPOCH` для того, чтобы заставить распознавать вновь создаваемый пакет как ``более новый''. Так как это новый релиз программы, то `PORTREVISION` обнуляется (или удаляется из файла `Makefile`).

    PORTNAME=      gtkmumble
    PORTVERSION=   0.2
    PORTEPOCH=     1

`PKGNAME` принимает значение `gtkmumble-0.2,1`

Следующий релиз имеет номер версии 0.3. Так как значение переменной `PORTEPOCH` никогда не уменьшается, что переменные, определяющие версии, теперь выглядят так:

    PORTNAME=      gtkmumble
    PORTVERSION=   0.3
    PORTEPOCH=     1

`PKGNAME` принимает значение `gtkmumble-0.3,1`

> Замечание: Если значение `PORTEPOCH` этим обновлением было бы сброшено в `0`, то кто-нибудь, имеющий установленный пакет `gtkmumble-0.10_1`, не смог бы опознать пакет `gtkmumble-0.3` как более новый, так как `3` было бы меньше, чем `10`. Помните, что в первую очередь это касается `PORTEPOCH`.

### 5.2.3. Переменные `PKGNAMEPREFIX` и `PKGNAMESUFFIX`

Две необязательные переменные, `PKGNAMEPREFIX` и `PKGNAMESUFFIX`, объединяются со значениями `PORTNAME` и `PORTVERSION` для формирования `PKGNAME` в форме `${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}`. Добейтесь того, чтобы это соответствовало нашим рекомендациям по правильному выбору названий для пакетов. В частности, в переменной `PORTVERSION` не разрешается использование дефиса (`-`). Кроме того, если в имени пакета присутствует часть `language-` или `-compiled.specifics` (смотрите ниже), то используйте переменные `PKGNAMEPREFIX` и `PKGNAMESUFFIX`, соответственно. Не делайте их частью значения переменной `PORTNAME`.

### 5.2.4. Соглашения по именованию пакетов

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

Имя пакета должно иметь вид ``[language[_region]]-name[[-]compiled.specifics]-version.numbers``.

Имя пакета определяется как `${PKGNAMEPREFIX}${PORTNAME}${PKGNAMESUFFIX}-${PORTVERSION}`. Вы должны задавать значения переменных в соответствии с этим форматом.

1. FreeBSD пытается поддерживать языки, на которых разговаривают её пользователи. Часть `language-` должна быть двухсимвольным сокращением от названия языка по стандарту ISO-639, если порт специфичен для конкретного языка. Примерами являются `ja` для японского, `ru` для русского, `vi` для вьетнамского, `zh` для китайского, `ko` для корейского и `de` для немецкого языков.

   Если ваш порт специфичен для конкретного региона внутри области использования языка, добавьте также двухсимвольный код страны. Примерами являются `en_US` для US English и `fr_CH` для Swiss French.

   Часть `language-` должна задаваться в переменной `PKGNAMEPREFIX`.

2. Первая буква части `name` должна быть в нижнем регистре. (Оставшаяся часть названия может содержать буквы в верхнем регистре, так что принимайте решение сами, когда преобразуете имя программного пакета, содержащего в имени некоторое количество заглавных букв.) Существует традиция именовать модули для `perl 5`, добавляя впереди `p5-` и преобразуя пару двоеточий в дефис; например, модуль `Data::Dumper` будет именоваться `p5-Data-Dumper`. Если программное обеспечение содержит в имени числа, дефисы или подчеркивания, то вы можете включить также и их (например, `kinput2`).

3. Если порт может быть построен с различными статически заданными значениями по умолчанию (обычно это часть имени каталога в семействе портов), то часть `-compiled.specifics` должна определять вкомпилированные значения по умолчанию (дефис не обязателен). Примерами являются размеры бумаги и шрифтов.

   Часть `-compiled.specifics` должна задаваться в переменной `PKGNAMESUFFIX`.

4. Строка с номером версии должна следовать за дефисом (`-`) и являться списком разделенных двоеточием чисел и букв в нижнем регистре. В частности, не разрешается иметь еще один дефис внутри строки с обозначением номера версии. Единственным исключением является строчка `pl` (означающая ``patchlevel''), которая может использоваться только тогда, когда у программного обеспечения нет старшего и младшего номера версии. Если в номер версии программного обеспечения включена строчка типа ``alpha'', ``beta'', ``rc'' или ``pre'', возьмите из неё первую букву и поставьте её непосредственно после точки. Если после таких строк номер версии ещё продолжается, то после буквы должно следовать число без дополнительной разделяющей точки.

   Смысл такого формата заключается в удобстве сортировки портов по номеру версии. В частности, следите за тем, чтобы компоненты номера версии разделялись точкой, и если там присутствует дата, то используйте формат ``yyyy`.`mm`.`dd``, но не ``dd`.`mm`.`yyyy`` или не совместимый с проблемой Г2000 ``yy`.`mm`.`dd``.

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

Имя дистрибутива | `PKGNAMEPREFIX` | `PORTNAME` | `PKGNAMESUFFIX` | `PORTVERSION` | Обоснование
--- | --- | --- | --- | --- | ---
mule-2.2.2 | (пусто) | mule | (пусто) | 2.2.2 | Изменений не потребовалось
XFree86-3.3.6 | (пусто) | XFree86 | (пусто) | 3.3.6 | Изменений не потребовалось
EmiClock-1.0.2 | (пусто) | emiclock | (пусто) | 1.0.2 | Для отдельных программ имена с заглавными буквами запрещены
rdist-1.3alpha | (пусто) | rdist | (пусто) | 1.3.a | Строчки типа `alpha` запрещены
es-0.9-beta1 | (пусто) | es | (пусто) | 0.9.b1 | Строчки типа `beta` запрещены
mailman-2.0rc3 | (пусто) | mailman | (пусто) | 2.0.r3 | Строчки типа `rc` запрещены
v3.3beta021.src | (пусто) | tiff | (пусто) | 3.3 | Что это такое было вообще?
tvtwm | (пусто) | tvtwm | (пусто) | pl11 | Всегда требуется указание номера версии
piewm | (пусто) | piewm | (пусто) | 1.0 | Всегда требуется указание номера версии
xvgr-2.10pl1 | (пусто) | xvgr | (пусто) | 2.10.1 | `pl` разрешено только при отсутствии старшего/младшего номера версии
gawk-2.15.6 | ja- | gawk | (пусто) | 2.15.6 | Версия на японском языке
psutils-1.13 | (пусто) | psutils | -letter | 1.13 | Размер бумаги задается статически во время построения пакета
pkfonts | (пусто) | pkfonts | 300 | 1.0 | пакет для шрифтов 300dpi

Если в исходном коде абсолютно нет информации о номере версии и не похоже, что автор собирается выпускать другую версию, то в качестве номера версии задайте просто `1.0` (как в примере с `piewm` выше). В противном случае спросите автора программы или используйте дату (``yyyy`.`mm`.`dd``) в качестве номера версии.

## 5.3. Разделение по категориям

### 5.3.1. `CATEGORIES`

В процессе создания пакета он помещается в каталог `/usr/ports/packages/All`, а в одном или более подкаталогов из `/usr/ports/packages` создаются на него ссылки. Имена этих подкаталогов определяются переменной `CATEGORIES`. Такая схема нужна для облегчения жизни пользователя, когда он сталкивается с массой пакетов на FTP-сервере или компакт-диске. Пожалуйста, посмотрите на список существующих категорий и выберите те из них, которые более всего подходят к вашему порту.

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

Если ваш порт действительно относится к чему-то, что абсолютно не имеет отношения ни к одной из существующих категорий, вы можете даже создать новую категорию. В этом случае, пожалуйста, пошлите письмо с вашим предложением на адрес Список рассылки, посвящённый Портам FreeBSD. Однако, вообще говоря, пока не наберётся более чем достаточного количества портов, которые можно отнести к предлагаемой вами категории, ваша идея будет отвергаться.

> Замечание: Время от времени кто-нибудь предлагает произвести реорганизацию категорий либо до двухуровневой, либо другого типа на основе ключевых слов. На данный момент из этих предложений ничего не получилось, потому что, хотя они просты в реализации, но предполагаемая переделка всей коллекции портов по меньшей мере приводит в уныние. Пожалуйста, прочтите историю этих предложений в архивах рассылок перед тем, как присылать свои соображения; более того, вы должны быть готовы представить работающий прототип.

### 5.3.2. Текущий список категорий

Вот текущий список категорий. Те, которые отмечены звёздочкой (`*`), являются виртуальными категориями--они не имеют собственного подкаталога в дереве портов. Они используются только в качестве вторичных категорий, и только для поиска.

> Замечание: Для каждой виртуальной категории имеется файл `pkg/COMMENT` с ее однострочным описанием в соответствующем подкаталоге (например, `archivers/pkg/COMMENT`).

Категория | Описание | Примечания
--- | --- | ---
`accessibility` | Порты для помощи пользователям с ограниченными возможностями. |
`afterstep*` | Порты, поддерживающие менеджер окон AfterStep. |
`arabic` | Поддержка арабского языка. |
`archivers` | Инструменты для работы с архивами. |
`astro` | Приложения, связанные с астрономией. |
`audio` | Поддержка работы со звуком. |
`benchmarks` | Утилиты для измерения производительности системы. |
`biology` | Программное обеспечение, связанное с биологией. |
`cad` | Инструменты Систем Автоматизированного Проектирования. |
`chinese` | Поддержка китайского языка. |
`comms` | Коммуникационное программное обеспечение. | В основном программы для работы с последовательным портом.
`converters` | Утилиты для преобразования символьных форматов. |
`databases` | Базы данных. |
`deskutils` | То, что было на столе до изобретения компьютеров. |
`devel` | Утилиты для разработки программного обеспечения. | Не помещайте сюда библиотеки просто потому что это библиотеки--если они подпадают под какую-то другую категорию, то их быть здесь не должно.
`dns` | Программное обеспечение для работы с DNS. |
`editors` | Редакторы общего назначения. | Специализированные редакторы относят к разделу для соответствующих инструментов (например, редактор математических формул попадает в категорию `math`).
`elisp*` | Порты для Emacs lisp. |
`emulators` | Эмуляторы других операционных систем. | Эмуляторы терминалов сюда не относятся--те, которые разработаны для X, должны быть в категории `x11`, а текстовые в `comms` или `misc`, в зависимости от конкретного их предназначения.
`finance` | Приложения для работы с деньгами, финансами и всем, что с этим связано. |
`french` | Поддержка французского языка. |
`ftp` | Клиенты и серверы FTP. | Если ваш порт понимает как FTP, так и HTTP, поместите его в категорию `ftp` и укажите вторичную категорию `www`.
`games` | Игры. |
`german` | Поддержка немецкого языка. |
`gnome*` | Порты Проекта GNOME. |
`graphics` | Графические утилиты. |
`haskell*` | Программное обеспечение, связанное с языком Haskell. |
`hebrew` | Поддержка иврита. |
`hungarian` | Поддержка венгерского языка. |
`ipv6*` | Программное обеспечение, связанное с IPv6. |
`irc` | Утилиты для работы с Internet Relay Chat. |
`japanese` | Поддержка японского языка. |
`java` | Программное обеспечение, связанное с языком Java. |
`kde*` | Порты проекта K Desktop Environment (KDE). |
`korean` | Поддержка корейского языка. |
`lang` | Языки программирования. |
`linux*` | Linux приложения и утилиты. |
`lisp*` | Программное обеспечение, связанное с языком Lisp. |
`mail` | Программы для работы с электронной почтой. |
`math` | Программное обеспечение для численных вычислений и другие утилиты, связанные с математикой. |
`mbone` | Приложения для MBone. |

`misc`

Различные утилиты

В основном то, что не попадает в другие категории. Это единственная категория, которая не должна указываться вместе с любой другой невиртуальной категорией. Если вы указываете `misc` вместе с чем-то ещё в строке `CATEGORIES`, это значит, что вы можете спокойно удалить `misc` и просто поместить порт в этот другой подкаталог! Если это возможно, попробуйте найти более подходящую, чем `misc`, категорию для вашего порта, так как здесь порты теряются.

`multimedia` | Программное обеспечение для работы с мультимедиа. |
`net` | Различное сетевое программное обеспечение. |
`net-mgmt` | Программное обеспечение для сетевого управления. |
`news` | Программное обеспечение для работы с конференциями USENET. |
`offix*` | Порты из пакета OffiX. |
`palm` | Программная поддержка Palm™. |
`parallel*` | Приложения, связанные с параллельными вычислениями. |
`pear*` | Порты, относящиеся к технологии Pear PHP. |
`perl5*` | Порты, которым для работы требуется Perl версии 5. |
`picobsd` | Порты для поддержки PicoBSD. |
`plan9*` | Различные программы из Plan9. |
`polish` | Поддержка польского языка. |
`portuguese` | Поддержка португальского языка. |
`print` | Программное обеспечение для печати. | Инструменты для вёрстки (просмотрщики и тому подобное) тоже относятся сюда. |
`python*` | Программное обеспечение, связанное с языком Python. |
`ruby*` | Программное обеспечение, связанное с языком Ruby. |
`russian` | Поддержка русского языка. |
`science` | Научные программы, которые не подпадают под другие категории, скажем, `astro`, `biology` или `math`. |
`security` | Программы, обеспечивающие безопасность системы. |
`shells` | Различные командные процессоры. |
`sysutils` | Системные утилиты. |
`tcl76*` | Порты, которым для работы нужен Tcl версии 7.6. |
`tcl80*` | Порты, которым для работы нужен Tcl версии 8.0. |
`tcl81*` | Порты, которым для работы нужен Tcl версии 8.1. |
`tcl82*` | Порты, которым для работы нужен Tcl версии 8.2. |
`tcl83*` | Порты, которым для работы нужен Tcl версии 8.3. |
`textproc` | Утилиты для обработки текстов. | Инструменты для вёрстки помещаются в категорию `print`, а не сюда.
`tk42*` | Порты, которым для работы нужен Tk версии 4.2. |
`tk80*` | Порты, которым для работы нужен Tk версии 8.0. |
`tk81*` | Порты, которым для работы нужен Tk версии 8.1. |
`tk82*` | Порты, которым для работы нужен Tk версии 8.2. |
`tk83*` | Порты, которым для работы нужен Tk версии 8.3. |
`tkstep80*` | Порты, которым для работы нужен TkSTEP версии 8.0. |
`ukrainian` | Поддержка украинского языка. |
`vietnamese` | Поддержка вьетнамского языка. |
`windowmaker*` | Порты, поддерживающие менеджер окон WindowMaker. |
`www` | Программное обеспечение, связанное с World Wide Web. | Поддержка языка HTML относится сюда же.

`x11`

X Window System и иже с ними.

Эта категория предназначена только для программного обеспечения, которое поддерживает саму оконную систему. Не помещайте сюда обычные приложения для X: большинство из них должны быть перенесены в другие категории `x11-*` (смотрите ниже). Если ваш порт является приложением для X, задайте `USE_XLIB` (что подразумевается при использовании `USE_IMAKE`) и укажите подходящую категорию.

`x11-clocks` | Часы для X11. |
`x11-fm` | Менеджеры файлов для X11. |
`x11-fonts` | Шрифты для X11 и утилиты для работы с ними. |
`x11-servers` | Серверы для X11. |
`x11-toolkits` | Пакеты разработчика для X11. |
`x11-wm` | Оконные менеджеры для X11. |
`zope*` | Поддержка Zope. |

### 5.3.3. Выбор правильной категории

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

- Сначала всегда идут категории, специфичные для языков. Например, если ваш порт устанавливает японские шрифты для X11, то строчка `CATEGORIES` должна иметь вид `japanese x11-fonts`.

- Более конкретные категории предпочтительней перед более общими. В частности, редактор HTML должен быть описан как `www editors`, а не наоборот. Кроме того, вы не должны указывать категорию `net`, если порт относится к одной из категорий `irc`, `mail`, `mbone`, `news`, `security` или `www`, так как `net` включается автоматически.

- `x11` используется как вторичная категория только в случае, если в качестве основной категории указан естественный язык. В частности, вам не нужно указывать `x11` в качестве категории для приложений X.

- Режимы для редактора Emacs должны помещаться в ту же категорию, что и приложение, которое поддерживается этим режимом, а не в `editors`. Например, режим Emacs для редактирования исходного кода некоторого языка программирования должен быть помещен в категорию `lang`.

- Если ваш порт решительным образом не подпадает ни под какую категорию, поместите его в `misc`.

Если вы не уверены в правильности выбора категории, пожалуйста, отметьте это в вашем сообщении через send-pr(1), чтобы мы могли обсудить это до того, как включить порт в Коллекцию. Если вы являетесь коммиттером, пошлите замечание на адрес Список рассылки, посвящённый Портам FreeBSD, чтобы мы могли обсудить это. Зачастую новые порты помещаются не в ту категорию только для того, чтобы их оттуда сразу же удалили. Это приводит к излишнему и ненужному росту основного хранилища исходных текстов.

## 5.4. Дистрибутивные файлы

Во второй части `Makefile` задаётся, какие файлы и откуда должны быть сгружены для того, чтобы построить порт.

### 5.4.1. `DISTNAME`

В переменной `DISTNAME` указывается имя порта так, как назвали его создатели программного обеспечения. Значение `DISTNAME` по умолчанию совпадает с `${PORTNAME}-${PORTVERSION}`, так что переопределяете её значение только в случае необходимости. `DISTNAME` используется только в двух местах. Во-первых, список дистрибутивных файлов (`DISTFILES`) по умолчанию состоит из `${DISTNAME}``${EXTRACT_SUFX}`. И во-вторых, предполагается, что дистрибутивный файл будет распакован в подкаталог с именем `WRKSRC`, значение которого по умолчанию есть не что иное, как `work/`${DISTNAME}``.

> Замечание: Значения переменных `PKGNAMEPREFIX` и `PKGNAMESUFFIX` не влияют на значение `DISTNAME`. Заметьте также, что если значение `WRKSRC` равно `work/`${PORTNAME}-${PORTVERSION}``, и в случае, когда оригинальный архив называется по имени, отличном от `${PORTNAME}-${PORTVERSION}${EXTRACT_SUFX}`, скорее всего, вы должны оставить `DISTNAME` как есть-- лучше переопределить `DISTFILES`, чем задавать значения как `DISTNAME`, так и `WRKSRC` (и, возможно, ещё и `EXTRACT_SUFX`).

### 5.4.2. `MASTER_SITES`

Содержит часть с каталогом FTP/HTTP-URL, которая указывает на оригинальный архив на сервере `MASTER_SITES`. Не забудьте лидирующий слэш (`/`)!

Макрос команды `make` будет пытаться воспользоваться этой переменной для получения дистрибутивного файла с помощью программы `FETCH`, если он не будет найден в системе.

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

Если оригинальный архив находится на одном из таких популярных серверов, как X-contrib, GNU или Perl CPAN, то указывайте эти сайты в простой форме при помощи `MASTER_SITE_`*`` (к примеру, `MASTER_SITE_XCONTRIB` или `MASTER_SITE_PERL_GNU`). Просто укажите в переменной `MASTER_SITES` одно из этих значений, а в переменной `MASTER_SITE_SUBDIR` задайте путь к архиву. Вот пример:

    MASTER_SITES=        ${MASTER_SITE_XCONTRIB}
    MASTER_SITE_SUBDIR=   applications

Эти переменные определены в файле `/usr/ports/Mk/bsd.sites.mk`. Всё время добавляются новые записи, так что обращайтесь к последней версии этого файла перед тем, как послать нам свой порт.

Пользователь может также задать значения переменных `MASTER_SITE_*` в файле `/etc/make.conf` для того, чтобы переопределить выбранные нами варианты, и использовать вместо них свои любимые зеркала этих популярных архивов.

### 5.4.3. `EXTRACT_SUFX`

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

К примеру, если дистрибутивный файл носит имя `foo.tgz`, а не более привычное `foo.tar.gz`, вы должны написать:

    DISTNAME=      foo
    EXTRACT_SUFX=  .tgz

Переменные `USE_BZIP2` и `USE_ZIP` автоматически устанавливают значение `EXTRACT_SUFX` в `.bz2` или `.zip` соответственно. Если ни одна из этих переменных не задана, то значение `EXTRACT_SUFX` по умолчанию устанавливается в `.tar.gz`.

> Замечание: Вам не нужно задавать значения `EXTRACT_SUFX` и `DISTFILES` одновременно.

### 5.4.4. `DISTFILES`

Иногда имена сгружаемых файлов не соответствуют имени порта. К примеру, файл может называться `source.tar.gz` или подобным образом. В других случаях исходный код приложения может располагаться в нескольких отличающихся архивах, и все они должны быть сгружены.

Если это ваш случай, то задайте в переменной `DISTFILES` список разделённых пробелами имён файлов, которые нужно сгрузить.

    DISTFILES=     source1.tar.gz source2.tar.gz

Если переменная `DISTFILES` не задана явно, то её значением по умолчанию будет `${DISTNAME}${EXTRACT_SUFX}`.

### 5.4.5. `EXTRACT_ONLY`

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

    DISTFILES=     source.tar.gz manual.html
    EXTRACT_ONLY=  source.tar.gz

Если ни один из `DISTFILES` не должен распаковываться, то установите пустое значение переменной `EXTRACT_ONLY`.

    EXTRACT_ONLY=

### 5.4.6. `PATCHFILES`

Если вашему порту требуются некоторых дополнительные патчи, которые доступны по FTP или HTTP, задайте имена этих файлов в переменной `PATCHFILES`, а в переменной `PATCH_SITES` укажите URL того каталога, в котором они содержатся (формат такой же, как для `MASTER_SITES`).

Если патч не относится к самому верху дерева исходных текстов (то есть `WRKSRC`), потому что он содержит некоторые дополнительные пути, установите соответственно значение переменной `PATCH_DIST_STRIP`. В частности, если все имена путей в патче имеют дополнительный путь `foozolix-1.0/` перед именем файла, то задайте `PATCH_DIST_STRIP=-p1`.

Не волнуйтесь, если патчи упакованы; они будут распакованы автоматически, если имена файлов оканчиваются на `.gz` или `.Z`.

Если патч распространяется вместе с какими-то другими файлами, такими, как документация, в виде tar-архива gzip, вы не можете просто использовать `PATCHFILES`. Если это ваш случай, добавьте имя и местоположение архива с патчем к `DISTFILES` и `MASTER_SITES`. Затем воспользуйтесь переменной `EXTRA_PATCHES` для указания этих файлов, и `bsd.port.mk` автоматически применит эти патчи. В частности, не копируйте файлы с патчами в каталог `PATCHDIR`--этот каталог может быть недоступным для записи.

> Замечание: Архив будет распакован вне исходного кода, как обычно, и к тому же его не нужно явно распаковывать, если это обычный архив gzip или compress. Если вы сделаете последнее, приложите дополнительные усилия для того, чтобы не перезаписать что-либо, уже существующее в этом каталоге. Также не забудьте добавить команду для удаления скопированного патча в цели `pre-clean`.

### 5.4.7. Несколько дистрибутивных файлов или патчей с различных серверов и подкаталогов (`MASTER_SITES:n`)

(Этот раздел можно считать немного ``повышенной трудности''; те, кто впервые знакомятся с этим текстом, могут пропустить этот раздел).

В этом разделе находится информация о механизме сгрузки, известном как `MASTER_SITES:n` и `MASTER_SITES_NN`. Далее мы будем называть этот механизм `MASTER_SITES:n`.

Сначала немного общей информации. В OpenBSD имеется полезная возможность, используемая в переменных `DISTFILES` и `PATCHFILES`, когда за именами файлов и патчей могут следовать идентификаторы типа `:n`, где `n` может быть из диапазона `[0-9]` и обозначать закреплённую группу. К примеру:

    DISTFILES=      alpha:0 beta:1

В OpenBSD дистрибутивный файл `alpha` будет связан с переменной `MASTER_SITES0`, но не с нашей общей переменной `MASTER_SITES`, а файл `beta` с переменной `MASTER_SITES1`.

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

Просто представьте себе 2 файла в `DISTFILES` и 20 сайтов в `MASTER_SITES`; сайты очень медленные, причём `beta` находится на всех сайтах из `MASTER_SITES`, а `alpha` может быть найден только на 20-м сайте. Будет неправильно проверять их все, если создатель знает об этом, не правда ли? Неподходящее начало для таких прекрасных выходных!

Теперь, когда вы получили общее представление, просто представьте ещё большее количество `DISTFILES` и `MASTER_SITES`. Уверен, что наш ``начальник системы поиска дистрибутивов'' представляет масштабы нагрузки на сеть, которую это даёт.

В последующих разделах информация будет даваться вместе с реализацией этой идеи во FreeBSD. Мы несколько улучшили концепцию OpenBSD.

#### 5.4.7.1. Упрощённая информация

В этом разделе рассказывается, как быстро подготовить точную сгрузку нескольких дистрибутивных файлов и патчей с разных сайтов и каталогов. Мы описываем здесь случай упрощённого использования `MASTER_SITES:n`. Для большинства сценариев этого будет достаточно. Однако, если вам нужна дополнительная информация, обратитесь к следующему разделу.

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

Чтобы это поддерживать, за каждой записью в `DISTFILES` может следовать символ двоеточия и ``имя метки''. За каждым сайтом, перечисленным в `MASTER_SITES`, тоже следует двоеточие и метка, которая указывает, какие файлы дистрибутива должны быть сгружены с этого сайта.

Например, рассмотрим приложение, исходный код которого разделён на две части, `source1.tar.gz` и `source2.tar.gz`, которые должны быть сгружены с двух различных источников. Файл `Makefile` порта будет содержать строчки типа Прим. 5-1.

Пример 5-1. Упрощённое использование `MASTER_SITES:n` с 1 файлом на каждом сайте

    MASTER_SITES=   ftp://ftp.example1.com/:source1 \
                    ftp://ftp.example2.com/:source2
    DISTFILES=      source1.tar.gz:source1 \
                    source2.tar.gz:source2

Несколько дистрибутивных файлов могут иметь одну и ту же метку. Продолжая предыдущий пример, положим, что имеется и третий дистрибутивный файл, `source3.tar.gz`, который должен быть сгружен с `ftp.example2.com`. Тогда файл `Makefile` будет написан как Прим. 5-2.

Пример 5-2. Упрощённое использование `MASTER_SITES:n` с более чем 1 файлом на каждом сервере

    MASTER_SITES=   ftp://ftp.example1.com/:source1 \
                    ftp://ftp.example2.com/:source2
    DISTFILES=      source1.tar.gz:source1 \
                    source2.tar.gz:source2 \
                    source3.tar.gz:source2

#### 5.4.7.2. Подробная информация

Прекрасно, но пример из предыдущего раздела не показал вам всё, что вам нужно? В этом разделе мы подробно опишем, как работает механизм `MASTER_SITES:n` точной сгрузки и как вы можете изменить ваши порты, чтобы это использовать.

1. За элементами могут следовать символы `:`n``, где `n` это `[^:,]+`, то есть `n` может теоретически быть любой алфавитно-цифровой строкой, но пока мы будем ограничивать их `[a-zA-Z_][0-9a-zA-Z_]+`.

   Более того, совпадение строк чувствительно к регистру; другими словами, `n` отличается от `N`.

   Однако следующие слова не могут использоваться для этих нужд, так как они имеют особое значение: `default`, `all` и `ALL` (они используются для своих нужд в ii). Кроме того, `DEFAULT` является специальным ключевым словом (посмотрите 3).

2. Элементы, за которыми следуют `:n`, принадлежат группе `n`, `:m` относится к группе `m` и так далее.

3. Элементы без таких суффиксов не относятся ни к какой группе, то есть они принадлежат к особой группе `DEFAULT`. Если вы укажете суффиксом любого элемента `DEFAULT`, вы просто выполните излишнюю работу, если только вы не хотите отнесения элемента как к группе `DEFAULT`, так и какой-то другой в одно и то же время (посмотрите на пункт 5).

   Следующие примеры равнозначны, но первый более предпочтителен:

       MASTER_SITES=   alpha

       MASTER_SITES=   alpha:DEFAULT

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

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

   Вместо того, чтобы повторять их несколько раз, каждый раз с разным постфиксом, мы можем перечислить несколько групп за раз в одном постфиксе. Например, `:m,n,o` определяет элемент, принадлежащий группам `m`, `n` и `o`.

   Все следующие примеры имеют один смысл, но последний является предпочтительным:

       MASTER_SITES=   alpha alpha:SOME_SITE

       MASTER_SITES=   alpha:DEFAULT alpha:SOME_SITE

       MASTER_SITES=   alpha:SOME_SITE,DEFAULT

       MASTER_SITES=   alpha:DEFAULT,SOME_SITE

6. Все серверы внутри определённой группы сортируются в соответствии с `MASTER_SORT_AWK`. Все группы в `MASTER_SITES` и `PATCH_SITES` тоже сортируются.

7. Семантика групп может использоваться в любой из следующих переменных `MASTER_SITES`, `PATCH_SITES`, `MASTER_SITE_SUBDIR`, `PATCH_SITE_SUBDIR`, `DISTFILES` и `PATCHFILES` в соответствии со следующим синтаксисом:

   1. Все элементы `MASTER_SITES`, `PATCH_SITES`, `MASTER_SITE_SUBDIR` и `PATCH_SITE_SUBDIR` должны заканчиваться символом прямого слэша `/`. Если какие-то элементы принадлежат каким-то группам, постфикс группы `:`n`` должен следовать сразу после терминирующего символа `/`. Механизм `MASTER_SITES:n` опирается на наличие терминирующего символа `/` во избежание совпадающих элементов, где `:n` является корректной частью элемента с вхождениями, где `:n` обозначает группу `n`. Для целей совместимости, так как терминирующий символ `/` ранее не требовался в элементах `MASTER_SITE_SUBDIR` и `PATCH_SITE_SUBDIR`, если символ, сразу предшествующий постфиксу, не является символом `/`, то `:n` будет считаться корректной частью элемента, а не постфиксом группы, даже если за элементом следует `:n`. Посмотрите Прим. 5-3 и Прим. 5-4.

      Пример 5-3. Подробное использование `MASTER_SITES:n` в `MASTER_SITE_SUBDIR`

          MASTER_SITE_SUBDIR=     old:n new/:NEW

      - Каталоги внутри группы `DEFAULT` -> old:n

      - Каталоги внутри группы `NEW` -> new

      Пример 5-4. Подробное использование `MASTER_SITES:n` с запятыми, несколькими файлами, несколькими серверами и несколькими подкаталогами

          MASTER_SITES=   http://site1/%SUBDIR%/ http://site2/:DEFAULT \
                          http://site3/:group3 http://site4/:group4 \
                          http://site5/:group5 http://site6/:group6 \
                          http://site7/:DEFAULT,group6 \
                          http://site8/%SUBDIR%/:group6,group7 \
                          http://site9/:group8
          DISTFILES=      file1 file2:DEFAULT file3:group3 \
                          file4:group4,group5,group6 file5:grouping \
                          file6:group7
          MASTER_SITE_SUBDIR=     directory-trial:1 directory-n/:groupn \
                                  directory-one/:group6,DEFAULT \
                                  directory

      Предыдущий пример приводит к следующей точной сгрузке. Серверы перечислены в точном порядке их использования.

      - `file1` будет сгружаться с

        - `MASTER_SITE_OVERRIDE`

        - http://site1/directory/

        - http://site1/directory-one/

        - http://site1/directory-trial:1/

        - http://site2/

        - http://site7/

        - `MASTER_SITE_BACKUP`

      - `file2` будет сгружаться точно также, как `file1`, так как они оба относятся к одной и той же группе

        - `MASTER_SITE_OVERRIDE`

        - http://site1/directory/

        - http://site1/directory-one/

        - http://site1/directory-trial:1/

        - http://site2/

        - http://site7/

        - `MASTER_SITE_BACKUP`

      - `file3` будет сгружен с

        - `MASTER_SITE_OVERRIDE`

        - http://site3/

        - `MASTER_SITE_BACKUP`

      - `file4` будет сгружаться с

        - `MASTER_SITE_OVERRIDE`

        - http://site4/

        - http://site5/

        - http://site6/

        - http://site7/

        - http://site8/directory-one/

        - `MASTER_SITE_BACKUP`

      - `file5` будет сгружен с

        - `MASTER_SITE_OVERRIDE`

        - `MASTER_SITE_BACKUP`

      - `file6` будет сгружаться с

        - `MASTER_SITE_OVERRIDE`

        - http://site8/directory-one/

        - `MASTER_SITE_BACKUP`

8. Как мне сгруппировать одну из специальных переменных из `bsd.sites.mk`, например, `MASTER_SITE_SOURCEFORGE`?

   Посмотрите Прим. 5-5.

   Пример 5-5. Подробное использование `MASTER_SITES:n` с `MASTER_SITE_SOURCEFORGE`

       MASTER_SITES=   http://site1/ ${MASTER_SITE_SOURCEFORGE:S/$/:sourceforge,TEST/}
       DISTFILES=      something.tar.gz:sourceforge

   `something.tar.gz` будет сгружаться со всех сайтов из `MASTER_SITE_SOURCEFORGE`.

9. Как мне использовать это с переменными `PATCH*`?

   Все примеры выполнялись с переменными `MASTER*`, и они работают точно также и для `PATCH*`, как это можно видеть в Прим. 5-6.

   Пример 5-6. Упрощённое использование `MASTER_SITES:n` с `PATCH_SITES`.

       PATCH_SITES=    http://site1/ http://site2/:test
       PATCHFILES=     patch1:test

#### 5.4.7.3. Что изменится для портов? А что не изменится?

1. Все имеющиеся порты остаются без изменений. Код для механизма `MASTER_SITES:n` активируется, если только есть элементы, которые заканчиваются на `:`n``, как и элементы в соответствии с вышеописанным синтаксисом, особенно как это показано в пункте 7.

2. Цели порт остаются теми же самыми: `checksum`, `makesum`, `patch`, `configure`, `build` и так далее. С обычными исключениями для `do-fetch`, `fetch-list`, `master-sites` и `patch-sites`.

   - `do-fetch`: использует новую группировку с постфиксами в `DISTFILES` и `PATCHFILES` с соответствующими элементами групп в `MASTER_SITES` и `PATCH_SITES`, которые используют группы из `MASTER_SITE_SUBDIR` и `PATCH_SITE_SUBDIR`. Посмотрите Прим. 5-4.

   - `fetch-list`: работает также, как старая цель `fetch-list` с тем исключением, что она группирует, как и `do-fetch`.

   - `master-sites` и `patch-sites`: (несовместимы со старыми версиями) только возвращают элементы группы `DEFAULT`; на самом деле они выполняют цели `master-sites-default` и `patch-sites-default` соответственно.

     Более того, использование целей `master-sites-all` или `patch-sites-all` предпочтительно для непосредственной проверки `MASTER_SITES` или `PATCH_SITES`. Также работа прямой проверки в последующих версиях не гарантируется. Посмотрите iii.ii для получения более дополнительной информации об этих новых целях.

3. Новые цели построения портов

   1. Имеются цели `master-sites-`n`` и `patch-sites-`n``, которые будут перечислять элементы соответствующей группы `n` из `MASTER_SITES` и `PATCH_SITES` соответственно. К примеру, `master-sites-DEFAULT` и `patch-sites-DEFAULT` обе будут возвращать элементы группы `DEFAULT`, `master-sites-test` и `patch-sites-test` группы `test` и так далее.

   2. Имеются новые цели `master-sites-all` и `patch-sites-all`, которые выполняют работу старых `master-sites` и `patch-sites`. Они возвращают элементы всех групп, как если бы они все принадлежали одной и той же группе с тем, что она перечисляет ровно столько `MASTER_SITE_BACKUP` и `MASTER_SITE_OVERRIDE`, как и группы, определённые в `DISTFILES` или `PATCHFILES`; соответственно для `master-sites-all` и `patch-sites-all`.

### 5.4.8. `DIST_SUBDIR`

Не позволяйте вашему порту засорять `/usr/ports/distfiles`. Если вашему порту требуется сгрузить много файлов, или он содержит имя файла, могущее вызвать конфликты с другими портами (например, `Makefile`), то укажите в переменной `DIST_SUBDIR` имя порта (должны подойти `${PORTNAME}` или `${PKGNAMEPREFIX}${PORTNAME}`). Это изменит значение переменной `DISTDIR` со значения по умолчанию `/usr/ports/distfiles` к значению `/usr/ports/distfiles/`DIST_SUBDIR``, и в результате всё, что требуется для порта, будет помещено в этот подкаталог.

Он заглянет также в подкаталог с тем же именем на основном резервном сервере `ftp.FreeBSD.org`. (Явное задание переменной `DISTDIR` в вашем файле `Makefile` этого не сделает, так что, пожалуйста, воспользуйтесь `DIST_SUBDIR`.)

> Замечание: Это не коснётся тех сайтов `MASTER_SITES`, которые вы указали в вашем файле `Makefile`.

## 5.5. `MAINTAINER`

Укажите здесь ваш адрес электронной почты. Пожалуйста. :-)

Заметьте, что в качестве значения для `MAINTAINER` допустимо использование только одного адреса без поля комментария. Должен использоваться формат `user@hostname.domain`. Пожалуйста, не включайте никакого описательного текста, например, вашего настоящего имени в эту строку--это несколько сбивает с толку `bsd.port.mk`. Вместо этого помещайте такую информацию в ваш `pkg-descr`.

Подробное описание того, за что отвечает лицо, поддерживающее порт, даётся в главе MAINTAINER в Makefiles.

Если мейнтейнер порта не ответил на запрос пользователя об обновлении в течение двух недель (исключая большие праздники), то это можно считать тайм-аутом от мейнтейнера, и обновление может быть выполнено без явного подтверждения от мейнтейнера. Если мейнтейнер не отвечает в течение трёх месяцев, то считается, что он отсутствует, и как мейнтейнер порта, о котором идёт речь, может быть заменён. Исключениями из этого правила является всё, что сопровождает Группа Менеджеров Дерева Портов FreeBSD `<portmgr@FreeBSD.org>` или Группа Офицеров Безопасности `<security-officer@FreeBSD.org>`. Запрещено делать любые несанкционированные изменения в портах, которые ведут эти группы.

За Группа Менеджеров Дерева Портов FreeBSD `<portmgr@FreeBSD.org>` оставляется право снять или назначить кого-либо мейнтейнером, по любой причине, а за the Группа Офицеров Безопасности `<security-officer@FreeBSD.org>` оставляется право лишать или назначать права на сопровождение порта по соображениям информационной безопасности.

## 5.6. `COMMENT`

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

    A cat chasing a mouse all over the screen

В файле `Makefile` переменная COMMENT должна следовать сразу за переменной MAINTAINER.

Пожалуйста, постарайтесь делать строку COMMENT длиной, меньшей, чем 70 символов, так как она выдаётся пользователям в качестве однострочного описания порта.

## 5.7. Зависимости

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

### 5.7.1. `LIB_DEPENDS`

Эта переменная указывает, от каких совместно используемых библиотек зависит порт. Это список пар `lib`:`dir`[`:target`] где `lib` - это имя библиотеки, `dir` - это каталог, в котором можно ее найти в случае, если ее нет на машине, и `target` - это цель, которую нужно вызвать в этом каталоге. Например,

     LIB_DEPENDS=
          jpeg.9:${PORTSDIR}/graphics/jpeg:install

проверит наличие библиотеки jpeg со старшим номером версии 9 и перейдет в подкаталог `graphics/jpeg` вашего дерева портов для ее построения и установки, если библиотека отсутствует. Часть `target` может быть опущена, если она равна `DEPENDS_TARGET` (по умолчанию `install`).

> Замечание: Часть `lib` - это аргумент, который передается команде `ldconfig -r | grep -wF`. В этой переменной не должно быть регулярных выражений.

Зависимость проверяется дважды, один раз внутри цели `extract`, а затем из цели `install`. Кроме того, имя зависимости помещается в пакет, так что pkg_add(1) будет автоматически его устанавливать, если его нет на пользовательской системе.

### 5.7.2. `RUN_DEPENDS`

В этой переменной перечисляются выполнимые файлы или файлы, от которых зависит работа порта. Это список пар вида `path`:`dir`[`:target`] где `path` - это имя программы или файла, а `dir` - каталог, в котором можно найти порт в случае, если его нет в системе, и `target` - это цель, которую нужно вызвать в этом каталоге. Если `path` начинается со слэша (`/`), он воспринимается как файл и его существование проверяется командой `test -e`; в противном случае предполагается, что это выполнимый файл и для определения того, имеется ли программа в пути поиска пользователя, используется команда `which -s`.

Например,

    RUN_DEPENDS=   ${LOCALBASE}/etc/innd:${PORTSDIR}/news/inn \
               wish8.0:${PORTSDIR}/x11-toolkits/tk80

проверит, существует ли файл или каталог `/usr/local/etc/innd` и построит и установит его из подкаталога `news/inn` дерева портов, если он не будет найден. Он также проверит, имеется ли выполнимый файл с именем `wish8.0` в вашем пути поиска, перейдет в подкаталог `x11-toolkits/tk80` вашего дерева портов для его построения и установки, если он не будет найден.

> Замечание: В приведенном примере `innd` является выполнимым файлом; если выполнимый файл находится в необычном для пользовательского маршрута поиска файлов месте, вы должны указать полный путь к файлу.

Зависимость проверяется внутри цели `install`. Кроме того, имя зависимости помещается в пакет, так что программа pkg_add(1) будет автоматически его устанавливать, если он не будет найден в пользовательской системе. Часть `target` может быть опущена, если она совпадает с `DEPENDS_TARGET`.

### 5.7.3. `BUILD_DEPENDS`

В этой переменной перечисляются выполнимые или обычные файлы, которые требуются порту для его построения. Как и `RUN_DEPENDS`, это список пар `path`:`dir`[`:target`] Например,

     BUILD_DEPENDS=
          unzip:${PORTSDIR}/archivers/unzip

будет проверять наличие выполнимого фала с именем `unzip` и перейдет в подкаталог `archivers/unzip` вашего дерева портов для его построения и установки, если последний не будет найден.

> Замечание: Под ``построением'' здесь понимается всё, от распаковки до компиляции. Зависимость проверяется из цели `extract`. Часть `target` может быть опущена, если она совпадает с `DEPENDS_TARGET`.

### 5.7.4. `FETCH_DEPENDS`

В этой переменной перечисляются выполняемые файлы или просто файлы, которые требуются порту для сгрузки. Как и предыдущие две переменные, это список пар `path`:`dir`[`:target`] Например,

     FETCH_DEPENDS=
          ncftp2:${PORTSDIR}/net/ncftp2

будет проверять наличие выполняемого файла с именем `ncftp2` и перейдет в каталог `net/ncftp2` вашего дерева портов для его построения и установки, если тот не будет найден.

Зависимость проверяется при выполнении цели `fetch`. Часть `target` может быть опущена, если она совпадает с `DEPENDS_TARGET`.

### 5.7.5. `EXTRACT_DEPENDS`

В этой переменной указываются программы или файлы, которые требуются для распаковки порта. Как и в предыдущих случаях, это список пар вида `path`:`dir`[`:target`]. Например,

    EXTRACT_DEPENDS=
              unzip:${PORTSDIR}/archivers/unzip

будет проверять наличие программы с именем `unzip`, и перейдёт в подкаталог `archivers/unzip` вашего дерева портов для её построения и установки, если такой программы не будет найдено.

Зависимость проверяется внутри цели `extract`. Часть `target` может быть опущена, если она совпадает с `DEPENDS_TARGET`.

> Замечание: Используйте эту переменную, только если распаковка не работает (по умолчанию предполагается использование `gzip`) и это не исправляется при помощи `USE_ZIP` или `USE_BZIP2`, которые описаны в Разд. 5.7.8.

### 5.7.6. `PATCH_DEPENDS`

Эта переменная указывает на программы или файлы, которые нужны порту для применения патчей. Как и в предыдущих случаях, это список пар вида `path`:`dir`[`:target`]. Например,

    PATCH_DEPENDS=
              ${NONEXISTENT}:${PORTSDIR}/java/jfc:extract

будет переходить в подкаталог `java/jfc` вашего дерева портов для построения и установки, если не найдёт нужной программы.

Зависимость проверяется внутри цели `patch`. Часть `target` может быть опущена, если она совпадает с `DEPENDS_TARGET`.

### 5.7.7. `DEPENDS`

Если имеется зависимость, которая не подпадает ни под одну из вышеперечисленных категорий, или ваш порт требует наличия исходных текстов другого порта в распакованном виде кроме того, что этот порт должен быть установлен, то воспользуйтесь этой переменной. Это список пар вида `dir`[`:target`], потому что, в отличие от предыдущих случаев, ничего не проверяется. Часть `target` может быть опущена, если она совпадает с `DEPENDS_TARGET`.

### 5.7.8. `USE_`*``

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

Таблица 5-1. Переменные `USE_`*``

Переменная | Смысл
--- | ---
`USE_BZIP2` | tar-архивы порта упакованы при помощи `bzip2`.
`USE_ZIP` | tar-архивы порта упакованы при помощи `zip`.
`USE_GMAKE` | Для построения порт требует наличия `gmake`.
`USE_PERL5` | Для построения и установки порта требуется `perl 5`. Обратитесь к Разд. 6.3 для получения информации о дополнительных переменных, которые связаны с `perl`.
`USE_X_PREFIX` | Порт устанавливается в каталог `X11BASE`, а не в `PREFIX`. Обратитесь к Разд. 6.4 для получения информации о дополнительных переменных, которые связаны с X11.
`USE_AUTOMAKE_VER` | В процессе своего построения порт использует GNU `automake`. Обратитесь к Разд. 6.5 для получения информации о дополнительных переменных, которые связаны с `automake`.
`USE_AUTOCONF_VER` | В процессе своего построения порт использует GNU `autoconf`. Обратитесь к Разд. 6.5 для получения информации о дополнительных переменных, которые связаны с `autoconf`.
`USE_LIBTOOL_VER` | В процессе своего построения порт использует GNU `libtool`. Обратитесь к Разд. 6.5 для получения информации о дополнительных переменных, которые связаны с `libtool`.
`GMAKE` | Полный маршрут до `gmake`, если он отсутствует в переменной окружения `PATH`.
`USE_BISON` | Для построения порт использует `bison`.
`USE_SDL` | Для построения и работы порт использует `SDL`. Обратитесь к разделу Разд. 6.13 для получения информации о том, как использовать `USE_SDL`.
`NO_INSTALL_MANPAGES` | Не использовать цель `install.man`.

Определите переменную `USE_XLIB=yes`, если ваш порт для установки требует X Window System (что подразумевается при использовании переменной `USE_IMAKE`). Определите переменную `USE_GMAKE=yes`, если ваш порт требует вместо стандартной для BSD утилиты `make` ее GNU-аналог. Задайте `USE_AUTOCONF_VER=213`, если порту для работы требуется GNU autoconf. Определите переменную `USE_QT=yes`, если ваш порт использует самую последнюю версию пакета qt. Укажите `USE_PERL5=yes` в случае, если вашему порту требуется версия 5 языка `perl`. (Последнее особенно важно, так как некоторые версии FreeBSD имеют `perl5` в составе системы, когда как другие - нет.)

### 5.7.9. Замечания касательно зависимостей

Как уже отмечено выше, целью, которая вызывается по умолчанию в случае, когда это требует зависимость, является `DEPENDS_TARGET`. Она по умолчанию есть `install`. Это пользовательская переменная; она нигде не определена в файле `Makefile` порта. Если вашему порту требуется особый метод обработки зависимости, воспользуйтесь частью `:target` переменной `*_DEPENDS` вместо того, чтобы переопределять `DEPENDS_TARGET`.

Когда вы набираете команду `make clean`, эта операция также выполняется и над зависимостями этого порта. Если вы не хотите, чтобы это случилось, определите переменную `NOCLEANDEPENDS` в вашем окружении. Это может быть особенно нужным, если порт имеет нечто, что занимает много времени на построение, в своём списке зависимостей, например, KDE, GNOME или Mozilla.

Чтобы безусловно зависеть от другого порта, укажите переменную `${NONEXISTENT}` в качестве первого поля переменной `BUILD_DEPENDS` или `RUN_DEPENDS`. Пользуйтесь этим, только когда вам нужно иметь исходный код другого порта. Вы можете сэкономить время на компиляции, указав также и цель. Например,

    BUILD_DEPENDS=   ${NONEXISTENT}:${PORTSDIR}/graphics/jpeg:extract

всегда будет переходить в каталог с портом `jpeg` и распаковывать его.

Не нужно использовать `DEPENDS`, если есть другой способ получить требуемый результат. Это может привести к тому, что какой-то другой порт всегда будет строиться (и по умолчанию устанавливаться). и такая зависимость отразится и на пакете. Если это именно то, что вам нужно, то вам, наверное, следует описывать это через `BUILD_DEPENDS` и `RUN_DEPENDS`--по крайней мере смысл будет более понятен.

### 5.7.10. Необязательные зависимости

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

Самым простым из этих механизмом является использование `WITHOUT_X11`. Если порт может быть построен как с поддержкой X, так и без оной, то обычно он должен строиться с поддержкой X. Если определена переменная `WITHOUT_X11`, то должна строиться версия, не поддерживающая X.

Различные части пакета GNOME имеют такие зависимости, хотя их гораздо труднее использовать. В `Makefile` можно использовать переменные `WANT_*` и `HAVE_*`. Если приложение может быть построено как с зависимостями, так и без зависимостей, перечисленных ниже, то в `Makefile` должна быть задана переменная `WANT_PKG` и версия, которая использует пакет `PKG`, будет строиться, если определена переменная `HAVE_PKG`.

На данный момент так работают переменные `WANT_*`, `WANT_GLIB`, `WANT_GTK`, `WANT_ESOUND`, `WANT_IMLIB` и `WANT_GNOME`.

### 5.7.11. Зацикленные зависимости фатальны

> Важно: Не помещайте зацикливающиеся зависимости в дерево портов!

Технология построения портов не защищена от зацикленных зависимостей. Если вы создадите такую, то у кого-нибудь и где-нибудь установка FreeBSD будет немедленно сломана, а у остальных сломается несколько позже. Это на самом деле очень трудно распознать; если вы сомневаетесь, то перед внесением изменений проверьте, что выполнили следующее: `cd /usr/ports; make index`. Этот процесс может быть достаточно медленным на старых машинах, хотя мы сможете спасти большое количество людей--включая себя--от грядущих бед.

## 5.8. Задание рабочего каталога

Каждый порт распаковывается в рабочий каталог, который должен быть доступным для записи. В системе портов по умолчанию `DISTFILES` распаковываются в каталог с именем `${DISTNAME}`. Другими словами, если вы задали:

    PORTNAME=      foo
    PORTVERSION=   1.0

то дистрибутивные файлы порта содержат каталог верхнего уровня, `foo-1.0`, и все файлы расположены в этом каталоге.

Если это не ваш случай, то имеется несколько переменных, которые вы можете переопределить.

### 5.8.1. `WRKSRC`

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

    WRKSRC=      ${WRKDIR}/foo

или, как вариант

    WRKSRC=      ${WRKDIR}/${PORTNAME}

### 5.8.2. `NO_WRKSUBDIR`

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

    NO_WRKSUBDIR= yes

## 5.9. `CONFLICTS`

Если ваш пакет не может существовать одновременно с другими (из-за конфликтов файлов, несовместимости во время выполнения и так далее), перечислите имена остальных пакетов в переменной `CONFLICTS`. Здесь вы можете использовать шаблоны командного процессора типа `*` и `?`. Имена пакетов должны выглядеть так же, как в `/var/db/pkg`. Пожалуйста, убедитесь, что `CONFLICTS` не содержит пакет самого этого порта или еще, что установка с помощью переменной `FORCE_PKG_REGISTER` больше не будет использоваться.

## 5.10. Механизмы построения

Если ваш пакет использует GNU-версию утилиты `make`, задайте `USE_GMAKE=yes`. Если ваш пакет использует `configure`, задайте `HAS_CONFIGURE=yes`. Если ваш пакет использует GNU-версию `configure`, задайте `GNU_CONFIGURE=yes` (это также подразумевает `HAS_CONFIGURE`). Если вы хотите передать дополнительные параметры в `configure` (список параметров представляет собой `--prefix=${PREFIX}` для GNU `configure` и пустую строку для не-GNU `configure`), укажите эти дополнительные параметры в `CONFIGURE_ARGS`. Если ваш пакет использует GNU-версию `autoconf`, задайте `USE_AUTOCONF_VER=213`. Это подразумевает `GNU_CONFIGURE`, и приведет к вызову `autoconf` до запуска `configure`.

> Замечание: Если ваш пакет использует GNU `configure`, и получающийся выполнимый файл имеет ``странное'' имя, типа `i386-portbld-freebsd4.7-``appname`, то вам необходимо, кроме всего прочего, переопределить переменную `CONFIGURE_TARGET`, указав цель в том виде, который требуют скрипты, генерируемые последними версиями `autoconf`. Добавьте следующую строку сразу после строки `GNU_CONFIGURE=yes` в вашем файле `Makefile`:

> `CONFIGURE_TARGET=--build=${MACHINE_ARCH}-portbld-freebsd${OSREL}`

Если ваш пакет является приложением для X, которое создает файлы `Makefile` из соответствующих файлов `Imakefile` при помощи утилиты `imake`, то задайте `USE_IMAKE=yes`. Это приведет к автоматическому запуску команды `xmkmf -a` на этапе конфигурирования. Если использование флага `-a` является для вашего порта проблематичным, задайте `XMKMF=xmkmf`. Если порт использует команду `imake`, но не воспринимает цель `install.man`, то должна быть задана переменная `NO_INSTALL_MANPAGES=yes`. Кроме того, автор программы должен быть пристрелен. :->

Если в файле `Makefile` из дистрибутива вашего порта в качестве главной цели для построения указано нечто, отличное от `all`, то задайте соответствующим образом переменную `ALL_TARGET`. То же самое касается целей `install` и `INSTALL_TARGET`.

# Глава 6. Особые соглашения

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

## 6.1. Динамические библиотеки

Если ваш порт устанавливает одну или несколько динамических библиотек, определите переменную `INSTALLS_SHLIB`, которая приведёт к запуску из `bsd.port.mk` команды `${LDCONFIG} -m` относительно каталога, в который устанавливается новая библиотека (как правило, это ``PREFIX`/lib`), во время выполнения цели `post-install` для её регистрации в кэше динамических библиотек. Эта переменная, если она определена, также приведёт к добавлению соответствующей пары команд `@exec /sbin/ldconfig -m` и `@unexec /sbin/ldconfig -R` в ваш файл `pkg-plist`, так что пользователь, устанавливающий пакет, сможет сразу же использовать динамическую библиотеку, а удаление пакета не приведёт к тому, что система будет предполагать, что библиотека всё ещё имеется в наличии.

Если нужно, вы можете переопределить каталог, в который по умолчанию устанавливается библиотека, задав переменную `LDCONFIG_DIRS`, в которой должны быть перечислены каталоги, в которые устанавливаются динамические библиотеки. Например, если ваш порт устанавливает динамические библиотеки в каталоги ``PREFIX`/lib/foo` и ``PREFIX`/lib/bar`, то вы можете в файле `Makefile` указать следующее:

    INSTALLS_SHLIB= yes
    LDCONFIG_DIRS=  %%PREFIX%%/lib/foo %%PREFIX%%/lib/bar

Заметьте, что значение переменной `LDCONFIG_DIRS` передаётся через sed(1), как и всё остальное в `pkg-plist`, так что подстановка значения `PLIST_SUB` также происходит здесь. Рекомендуется использовать `%%PREFIX%%` для `PREFIX`, `%%LOCALBASE%%` для `LOCALBASE` и `%%X11BASE%%` для `X11BASE`.

## 6.2. Порты с ограничениями на распространение

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

> Важно: На вас, как на человека, портирующего приложение, ложится обязанность прочесть лицензионные соглашения на программное обеспечение и удостовериться, что проект FreeBSD не будет являться их нарушителем, если будет заниматься распространением исходного кода или в бинарном виде по FTP/HTTP или на CD-ROM. Если у вас возникли сомнения, то, пожалуйста, обратитесь в Список рассылки, посвящённый Портам FreeBSD.

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

### 6.2.1. `NO_PACKAGE`

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

Однако файлы `DISTFILES` могут свободно зеркалироваться по FTP/HTTP. Они также могут распространяться, используя CD-ROM (или на похожих носителях), если не установлена переменная `NO_CDROM`.

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

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

### 6.2.2. `NO_CDROM`

Эта переменная указывает на то, что, хотя мы имеем право создавать бинарные пакеты, мы не можем помещать эти пакеты или файлы `DISTFILES` порта на CD-ROM (или на похожие носители) для перепродажи. Однако бинарные пакеты и файлы `DISTFILES` порта будут оставаться доступными посредством FTP/HTTP.

Если эта переменная устанавливается вместе с `NO_PACKAGE`, то только файлы порта `DISTFILES` будут доступны, и только посредством FTP/HTTP.

В качестве значения `NO_CDROM` должна указываться строка, описывающая причины, по которым порт не может распространяться на CD-ROM. К примеру, это применяется, если лицензионное соглашение приложения предполагает только его ``некоммерческое'' использование.

### 6.2.3. `RESTRICTED`

Задайте эту переменную, если лицензия на приложение не позволяет ни зеркалировать файлы `DISTFILES`, ни распространять бинарный пакет через FTP/HTTP или на CD-ROM.

Ни `NO_CDROM`, ни `NO_PACKAGE` не стоит устанавливать вместе с `RESTRICTED`, так как последняя переменная подразумевает первые две.

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

### 6.2.4. `RESTRICTED_FILES`

Если заданы `RESTRICTED` или `NO_CDROM`, то значение этой переменной по умолчанию соответствует `${DISTFILES} ${PATCHFILES}`, в противном случае она пуста. Если ограничены в распространении лишь некоторые из дистрибутивных файлов, то в этой переменной задаётся их список.

Обратите внимание, что при включении порта в дерево исходных текстов системы коммиттер должен добавить запись в файл `/usr/ports/LEGAL` для каждого из перечисленных файлов, в точности описав, что подразумевают ограничения.

## 6.3. Использование `perl`

Таблица 6-1. Переменные для портов, использующих `perl`

Переменная | Смысл
--- | ---
`USE_PERL5` | Указывает на то, что порт использует `perl 5` для своего построения и работы.
`USE_PERL5_BUILD` | Указывает на то, что для построения порт использует `perl 5`.
`USE_PERL5_RUN` | Указывает на то, что для работы порт использует `perl 5`.
`PERL` | Полный маршрут к `perl 5`, либо в системе, либо установленного из портов, но без номера версии. Используйте это, если вам нужно заменить строки ```#!`'' в скриптах.
`PERL_CONFIGURE` | Конфигурация при помощи MakeMaker языка Perl. Влечёт `USE_PERL5`.

Переменные только для чтения |
`PERL_VERSION` | Полный номер версии установленного `perl` (например, `5.00503`).
`PERL_VER` | Краткий номер версии установленного `perl` (например, `5.005`).
`PERL_LEVEL` | Версия установленного `perl` в форме целого числа вида `MNNNPP` (например, `500503`).
`PERL_ARCH` | Место, где `perl` хранит архитектурно-зависимые библиотеки. По умолчанию это `${ARCH}-freebsd`.
`PERL_PORT` | Название установленного порта `perl`, (к примеру, `perl5`).
`SITE_PERL` | Имя каталога, куда помещаются специфичные для сайта пакеты `perl`. Это значение добавляется к PLIST_SUB.

## 6.4. Использование X11

Таблица 6-2. Переменные для портов, использующих X

`USE_X_PREFIX` | Порт устанавливается в каталог `X11BASE`, а не в `PREFIX`.
`USE_XLIB` | Порт использует библиотеки X.
`USE_MOTIF` | Порт использует инструментальный пакет Motif. Предусматривает включение `USE_XPM`.
`USE_IMAKE` | Порт использует `imake`. Предусматривает включение `USE_X_PREFIX`.
`XMKMF` | Задаётся маршрут до `xmkmf`, если он отсутствует в переменной окружения `PATH`. По умолчанию это `xmkmf -a`.

## 6.5. Использование `automake`, `autoconf` и `libtool`

Таблица 6-3. Переменные для портов, использующих automake, autoconf или libtool

Переменная | Смысл
--- | ---
`AUTOMAKE` | Полный маршрут к `automake`, если его нет в переменной окружения `PATH`.
`USE_AUTOMAKE_VER` | Порт использует `automake`. Корректными значениями для этой переменной являются `14` и `15`, и они соответственно определяют значения переменных `AUTOMAKE_DIR` и `ACLOCAL_DIR`.
`AUTOMAKE_ARGS` | Один или более аргументов командной строки для передачи `AUTOMAKE`, если задана переменная `USE_AUTOMAKE_VER`.
`AUTOMAKE_ENV` | Одна или большее количество переменных окружения (и их значений), задаваемых перед запуском `AUTOMAKE`.
`ACLOCAL` | Задаёт маршрут для GNU `aclocal`, если его нет в переменной окружения `PATH`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOMAKE_VER`.
`ACLOCAL_DIR` | Задаёт маршрут для совместно используемого каталога GNU `aclocal`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOMAKE_VER`.
`AUTOMAKE_DIR` | Задаёт маршрут для совместно используемого каталога GNU `automake`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOMAKE_VER`.
`USE_AUTOCONF_VER` | Указывает на то, что порт использует `autoconf`. Подразумевает `GNU_CONFIGURE`. По умолчанию значение равно 213.
`AUTOCONF` | Задаёт маршрут для GNU `autoconf`, если его нет в переменной окружения `PATH`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOCONF_VER`.
`AUTOCONF_ARGS` | Аргументы командной строки для передачи в `autoconf`.
`AUTOCONF_ENV` | Определяет значения пар ``variable`=`value`` в окружении перед запуском `autoconf`.
`USE_AUTOHEADER_VER` | Указывает, что порт использует `autoheader`. Подразумевает `USE_AUTOCONF_VER`. Значение по умолчанию равно 213.
`AUTOHEADER` | Задаёт маршрут для GNU `autoheader`, если его нет в переменной окружения `PATH`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOCONF_VER`.
`AUTORECONF` | Задаёт маршрут для GNU `autoreconf`, если его нет в переменной окружения `PATH`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOCONF_VER`.
`AUTOSCAN` | Задаёт маршрут для GNU `autoscan`, если его нет в переменной окружения `PATH`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOCONF_VER`.
`AUTOIFNAMES` | Задаёт маршрут для GNU `autoifnames`, если его нет в переменной окружения `PATH`. По умолчанию задаётся в соответствии со значением переменной `USE_AUTOCONF_VER`.
`USE_LIBTOOL_VER` | Порт использует `libtool`. Предусматривает включение `GNU_CONFIGURE`. Значение по умолчанию равно 13.
`LIBTOOL` | Задаёт маршрут для `libtool`, если его нет в переменной окружения `PATH`.
`LIBTOOLFILES` | Файлы для обработки `libtool`. По умолчанию это `aclocal.m4`, если определена переменная `USE_AUTOCONF`, и `configure` в противном случае.
`LIBTOOLFLAGS` | Дополнительные флаги для передачи в `ltconfig`. По умолчанию это `--disable-ltlibs`.

## 6.6. Использование GNOME

Для задания того, какие компоненты GNOME использует конкретный порт, проект FreeBSD/GNOME использует собственный набор переменных. На странице проекта FreeBSD/GNOME размещён исчерпывающий список этих переменных.

## 6.7. Использование KDE

Таблица 6-4. Переменные для портов, которые используют KDE

`USE_QT_VER` | Порт использует инструментальный пакет Qt. Возможными значениями являются `1`, `2` и `3`; каждый вариант задаёт старший номер используемой версии Qt. Задаются соответствующие значения по умолчанию переменных `MOC` и `QTCPPFLAGS`.
`USE_KDELIBS_VER` | Порт использует библиотеки KDE. Возможными значениями являются `1`, `2` и `3`; каждый вариант определяет старший номер используемой версии KDE. Предусматривается включение `USE_QT_VER` соответствующей версии.
`USE_KDEBASE_VER` | Порт использует в качестве установки корневой каталог KDE. Возможными значениями являются `1`, `2` и `3`; каждый вариант определяет старший номер используемой версии KDE. Предусматривается включение `USE_KDELIBS_VER` соответствующей версии.
`MOC` | Задаёт маршрут до `moc`. По умолчанию устанавливается в соответствии со значением переменной `USE_QT_VER`.
`QTCPPFLAGS` | Задаётся значение `CPPFLAGS` для использования при обработке кода Qt. По умолчанию задаётся в соответствие со значением переменной `USE_QT_VER`.

## 6.8. Использование Bison

Этот раздел ещё предстоит написать.

## 6.9. Использование Java

### 6.9.1. Задание переменных

Если вашему порту необходимо наличие Java™ Development Kit (JDK) для построения, работы или даже распаковки дистрибутивного файла, то в нём должна быть задана переменная `USE_JAVA`.

В Коллекции Портов присутствуют несколько JDK различных разработчиков и разных версий. Если ваш порт должен использовать одну из этих версий, то вы должны указать, какую именно. Самой последней версией является `java/jdk14`.

Таблица 6-5. Переменные, которые которые могут задаваться портами, использующими Java

Переменная | Значение
--- | ---
`USE_JAVA` | Должна быть определена для того, что последующие переменные вступили в действие.
`JAVA_VERSION` | Список версий Java, перечисленных через пробел, подходящих для порта. Опциональный знак `"+"` позволяет вам указать диапазон версий (возможные значения: `1.1[+] 1.2[+] 1.3[+] 1.4[+]`).
`JAVA_OS` | Список операционных систем, перечисленных через пробел, порты JDK для которых подходят для порта (возможные значения: `native linux`).
`JAVA_VENDOR` | Список разработчиков портов JDK, перечисленных через пробел, которые подходят для порта (возможные значения: `freebsd bsdjava sun ibm blackdown`).
`JAVA_BUILD` | Если задана, то означает, что выбранный порт JDK должен быть добавлен к зависимостям порта для его построения.
`JAVA_RUN` | Если задана, то означает, что выбранный порт JDK должен быть добавлен в зависимостям порта для его работы.
`JAVA_EXTRACT` | Если задана, то означает, что выбранный порт JDK должен быть добавлен в зависимостям порта для распаковки его дистрибутивных файлов.

`USE_JIKES`

Должен или нет порт использовать компилятор байт-кода `jikes` для своего построения. Если значение этой переменной не определено, то порт будет использовать `jikes` (при наличии последнего) для своего построения. Вы можете также явно запретить или принудить использовать `jikes` (указав в качестве значения `'no'` или `'yes'`). В последнем случае `devel/jikes` будет добавлен к зависимостям порта, нужным для его построения.

Ниже перечисляются все значения, которые принимают переменные после задания переменной `USE_JAVA`:

Таблица 6-6. Переменные, доступные в портах, использующих Java

Переменная | Значение
--- | ---
`JAVA_PORT` | Название порта JDK (к примеру, `'java/jdk14'`).
`JAVA_PORT_VERSION` | Полное наименовании версии порта JDK (к примеру, `'1.4.2'`). Если вам нужны только первые две цифры номера версии, используйте конструкцию `${JAVA_PORT_VERSION:C/^([0-9])\.([0-9])(.*)$/\1.\2/}`.
`JAVA_PORT_OS` | Операционная система, используемая портом JDK (к примеру, `'linux'`).
`JAVA_PORT_VENDOR` | Разработчик порта JDK (к примеру, `'sun'`).
`JAVA_PORT_OS_DESCRIPTION` | Описание операционной системы, используемой портом JDK (к примеру, `'Linux'`).
`JAVA_PORT_VENDOR_DESCRIPTION` | Описание разработчика порта JDK (к примеру, `'FreeBSD Foundation'`).
`JAVA_HOME` | Маршрут к установочному каталогу JDK (к примеру, `'/usr/local/jdk1.3.1'`).
`JAVAC` | Маршрут к используемому компилятору Java (к примеру, `'/usr/local/jdk1.1.8/bin/javac'` или `'/usr/local/bin/jikes'`).
`JAR` | Маршрут к используемой утилите `jar` (к примеру, `'/usr/local/jdk1.2.2/bin/jar'` или `'/usr/local/bin/fastjar'`).
`APPLETVIEWER` | Маршрут к утилите `appletviewer` (к примеру, `'/usr/local/linux-jdk1.2.2/bin/appletviewer'`).
`JAVA` | Маршрут к выполняемому файлу `java`. Используйте его для запуска Java-программ (к примеру, `'/usr/local/jdk1.3.1/bin/java'`).
`JAVADOC` | Маршрут к вспомогательной программе `javadoc`.
`JAVAH` | Маршрут к программе `javah`.
`JAVAP` | Маршрут к программе `javap`.
`JAVA_KEYTOOL` | Маршрут к вспомогательной программе `keytool`. Эта переменная определена, только если JDK соответствует Java 1.2 или более старшей версии.
`JAVA_N2A` | Маршрут к утилите `native2ascii`.
`JAVA_POLICYTOOL` | Маршрут к программе `policytool`. Эта переменная определена, только если JDK соответствует Java 1.2 или более старшей версии.
`JAVA_SERIALVER` | Маршрут к вспомогательной программе `serialver`.
`RMIC` | Маршрут к генератору каркаса программ RMI, утилите `rmic`.
`RMIREGISTRY` | Маршрут к программе регистрации RMI, `rmiregistry`.
`RMID` | Маршрут к программе-даемону RMI `rmid`. Эта переменная определена, только если JDK соответствует Java 1.2 или более старшей версии.
`JAVA_CLASSES` | Маршрут к архиву, который содержит файлы классов JDK. Для JDK 1.2 и более старших версий её значение соответствует `${JAVA_HOME}/jre/lib/rt.jar`. JDK предыдущих версий использовали `${JAVA_HOME}/lib/classes.zip`.

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

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

Таблица 6-7. Константы, определённые для портов, использующих Java

Константа | Значение
--- | ---
`JAVASHAREDIR` | Корневой каталог для всего, что связано с Java. По умолчанию: `${PREFIX}/share/java`.
`JAVAJARDIR` | Каталог, в который должны устанавливаться JAR-файлы. По умолчанию: `${JAVASHAREDIR}/classes`.

### 6.9.2. Практические рекомендации

При портировании Java-библиотеки ваш порт должен устанавливать JAR-файл(ы) в каталог `${JAVAJARDIR}`, а все остальные данные в каталог `${JAVASHAREDIR}/${PORTNAME}` (за исключением документации, о которой пойдёт речь ниже). Для уменьшения размера упакованного файла вы можете сослаться на JAR-файл(ы) непосредственно в файле `Makefile`. Просто воспользуйтесь следующей директивой (в которой `myport.jar` является именем JAR-файла, устанавливаемого как часть порта):

    PLIST_FILES+= ${JAVAJARDIR:S,^${PREFIX}/,,}/myport.jar

При портировании Java-приложения порт обычно устанавливает всё в один каталог (в том числе все свои JAR-зависимости). В этом отношении настоятельно рекомендуется использование `${JAVASHAREDIR}/${PORTNAME}`. На усмотрение создателя порта остаётся решение вопроса о том, устанавливать ли дополнительные JAR-зависимости в этот каталог или напрямую использовать уже установленные (из каталога `${JAVAJARDIR}`).

Вне зависимости от типа вашего порта (библиотека это или приложение), дополнительная документация должна быть устанавливаться в тоже самое место, что и для других портов. Известно, что в зависимости от используемой версии JDK утилита JavaDoc генерирует различные наборы файлов. Для портов, которые не привязаны к использованию определённой версии JDK, таким образом становится проблематичным определить список файлов для упаковки (`pkg-plist`). Это одна из причин, по которой создателям портов настоятельно рекомендуется использовать макрос `PORTDOCS`. Более того, даже если вы сможете угадать набор файлов, который будет сгенерирован утилитой `javadoc`, размер получающегося файла `pkg-plist` голосует за использование `PORTDOCS`.

Значением по умолчанию для переменной `DATADIR` является `${PREFIX}/share/${PORTNAME}`. Хорошей идеей является переопределение для Java-портов значения `DATADIR` как `${JAVASHAREDIR}/${PORTNAME}`. На самом деле `DATADIR` автоматически добавляется к `PLIST_SUB` (это описано здесь), так что вы сможете использовать `%%DATADIR%%` непосредственно в `pkg-plist`.

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

Все возможности, которые были описаны в этом разделе, реализованы в файле `bsd.java.mk`. Если вы предположите, что вашему порту требуется менее тривиальная поддержка Java, пожалуйста, взгляните сначала на журнал изменений bsd.java.mk в CVS, так как для документирования последних изменений требуется какое-то время. Затем, если вы думаете, что не хватающая вам поддержка окажется полезной для многих других портов Java, обсудите ваш вопрос в Список рассылки, посвящённый поддержке Java во FreeBSD.

Хотя в базе сообщений об ошибках для соответствующих PR имеется категория `java`, она относится к работе над портированием JDK, которые проводит Проект FreeBSD Java. Таким образом, вы должны относить свой Java-порт, как и любой другой, к категории `ports`, если решаемый вами вопрос не относится ни к реализации JDK, ни к `bsd.java.mk`.

## 6.10. Использование Python

Этот раздел ещё предстоит написать.

## 6.11. Использование Emacs

Этот раздел ещё предстоит написать.

## 6.12. Использование Ruby

Этот раздел ещё предстоит написать.

## 6.13. Использование SDL

Переменная `USE_SDL` используется для автоматической настройки зависимостей для портов, использующих библиотеки на основе SDL, такие как `devel/sdl12` или `x11-toolkits/sdl_gui`.

На данный момент распознаются следующие SDL-библиотеки:

- sdl: `devel/sdl12`

- gfx: `graphics/sdl_gfx`

- gui: `x11-toolkits/sdl_gui`

- image: `graphics/sdl_image`

- ldbad: `devel/sdl_ldbad`

- mixer: `audio/sdl_mixer`

- mm: `devel/sdlmm`

- net: `net/sdl_net`

- sound: `audio/sdl_sound`

- ttf: `graphics/sdl_ttf`

Таким образом, если порт имеет зависимость от `net/sdl_net` и `audio/sdl_mixer`, то строка будет следующей:

    USE_SDL=   net mixer

Зависимость от порта `devel/sdl12`, который требуется для `net/sdl_net` и `audio/sdl_mixer` будет также автоматически добавлен.

Если вы используете `USE_SDL`, то он автоматически:

- Добавляет зависимость от sdl12-config к `BUILD_DEPENDS`

- Добавляет переменную `SDL_CONFIG` к `CONFIGURE_ENV`

- Добавляет зависимости от указанных библиотек к `LIB_DEPENDS`

Для проверки наличия библиотеки SDL вы можете делать это при помощи переменной `WANT_SDL`:

    WANT_SDL=yes

    .include <bsd.port.pre.mk>

    .if ${HAVE_SDL:Mmixer}!=""
    USE_SDL+=   mixer
    .endif

    .include <bsd.port.post.mk>

# Глава 7. `MASTERDIR`

Если вашему порту требуется построение довольно различающихся версий пакетов через переменную (задающую, например, разрешение, или размер бумаги), которая принимает различные значения, создайте для каждого пакета отдельный подкаталог, чтобы пользователям было легче определить, каким пакетом воспользоваться, но попробуйте использовать совместно между портами как можно больше файлов. В типичном случае вам потребуются только очень короткие файлы `Makefile` во всех каталогах, кроме одного, если вы будете использовать переменные с умом. В отдельных файлах `Makefile` вы можете использовать переменную `MASTERDIR` для указания каталога, в котором находятся все остальные файлы. Также используйте переменную как часть `PKGNAMESUFFIX`, чтобы пакеты имели разные имена.

Продемонстрируем это на примере. Вот часть файла `japanese/xdvi300/Makefile`:

    PORTNAME=       xdvi
    PORTVERSION=    17
    PKGNAMEPREFIX=  ja-
    PKGNAMESUFFIX=  ${RESOLUTION}
     :
    # default
    RESOLUTION?=   300
    .if ${RESOLUTION} != 118 && ${RESOLUTION} != 240 && \
           ${RESOLUTION} != 300 && ${RESOLUTION} != 400
           @${ECHO} "Error: invalid value for RESOLUTION: \"${RESOLUTION}\""
           @${ECHO} "Possible values are: 118, 240, 300 (default) and 400."
           @${FALSE}
    .endif

Порт `japanese/xdvi300` содержит также все обычные патчи, файлы для пакета и так далее. Если вы введете здесь команду `make`, она возьмет в качестве разрешения значение по умолчанию (300) и построит порт обычным образом.

Для другого разрешения приведем полный `xdvi118/Makefile`:

    RESOLUTION=    118
    MASTERDIR=  ${.CURDIR}/../xdvi300

    .include "${MASTERDIR}/Makefile"

(`xdvi240/Makefile` и `xdvi400/Makefile` похожи). Задание `MASTERDIR` говорит `bsd.port.mk`, что обычный набор подкаталогов типа `FILESDIR` и `SCRIPTDIR` находится в каталоге `xdvi300`. Строчка `RESOLUTION=118` переопределят строку `RESOLUTION=300` в файле `xdvi300/Makefile` и порт будет построен с разрешением 118.

# Глава 8. Версии динамических библиотек

Первым делом прочтите, пожалуйста, наши правила нумерации версий динамических библиотек для понимания того, что делать с версиями совместно используемых библиотек вообще. Не полагайтесь слепо на то, что авторы программного обеспечения знают, что творят; многие это не понимают. Очень важно с точностью следовать всем этим правилам, так как мы получаем достаточно уникальную ситуацию, когда пытаемся иметь несколько наборов потенциально несовместимых программных пакетов. Невнимательное включение портов вызывало большие проблемы относительно совместно используемых библиотек в прошлом (вы когда либо задумывались, почему порт `jpeg-6b` имеет библиотеку версии 9?). Если не уверены, пошлите сообщение по адресу Список рассылки, посвящённый Портам FreeBSD. В большинстве случаев ваша работа заканчивается определением правильного номера динамической библиотеки и созданием соответствующих патчей для реализации этого.

# Глава 9. Страницы Справочника

Переменные `MAN[1-9LN]` автоматически добавят любые страницы Справочника к файлу `pkg-plist` (это означает, что вам не нужно указывать страницы Справочника в файле `pkg-plist`--обратитесь к главе о генерации файла PLIST для получения более подробной информации). Это также позволяет на этапе установки автоматически упаковывать и распаковывать страницы Справочника в зависимости от значения переменной `NOMANCOMPRESS` в файле `/etc/make.conf`.

Если ваш порт пытается задать несколько имен для страниц Справочника при помощи символических или жестких ссылок, то вы должны использовать переменную `MLINKS`, чтобы указать на это. Ссылка, установленная вашим портом, будет уничтожена и создана заново сценарием `bsd.port.mk` для проверки того, что она указывает на правильный файл. Любые страницы Справочника, перечисленные в переменной MLINKS, не должны фигурировать в файле `pkg-plist`.

Для указания того, что страницы Справочника нужно сжимать во время установки, используйте переменную `MANCOMPRESSED`. Эта переменная может принимать три значения - `yes`, `no` и `maybe`. `yes` означает, что страницы Справочника устанавливаются уже сжатыми, `no` означает, что они не сжимаются и `maybe` означает, что программное обеспечение принимает во внимание значение переменной `NOMANCOMPRESS`, так что сценарию `bsd.port.mk` ничего дополнительно делать не нужно.

Значение переменной `MANCOMPRESSED` автоматически устанавливается в `yes`, если переменная `USE_IMAKE` задана, а `NO_INSTALL_MANPAGES` нет, и в значение `no` в противном случае. Вам не нужно задавать ее явно, если значение по умолчанию подходит вашему порту.

Если ваш порт определяет корнем для файлов Справочника каталог, отличный от `PREFIX`, вы можете использовать переменную `MANPREFIX`, чтобы задать его явно. Кроме того, если страницы только некоторых разделов помещаются в нестандартное место, например, в случае портов модулей языка `perl` Perl, вы можете установить маршруты к справочным страницам индивидуально, при помощи `MAN`sect`PREFIX` (где `sect` принимает значения `1-9`, `L` или `N`).

Если страницы Справочника помещаются в подкаталоги, соответствующие некоторому языку, то задайте название языка языка в переменной `MANLANG`. Значение этой переменной по умолчанию равно `""` (то есть только английский язык).

Вот пример, в котором приводятся все случаи.

    MAN1=         foo.1
    MAN3=          bar.3
    MAN4=          baz.4
    MLINKS=        foo.1 alt-name.8
    MANLANG=       "" ja
    MAN3PREFIX=    ${PREFIX}/share/foobar
    MANCOMPRESSED= yes

Здесь указано, что этот порт устанавливает 6 файлов:

    ${PREFIX}/man/man1/foo.1.gz
    ${PREFIX}/man/ja/man1/foo.1.gz
    ${PREFIX}/share/foobar/man/man3/bar.3.gz
    ${PREFIX}/share/foobar/man/ja/man3/bar.3.gz
    ${PREFIX}/man/man4/baz.4.gz
    ${PREFIX}/man/ja/man4/baz.4.gz

Кроме того, файл `${PREFIX}/man/man8/alt-name.8.gz` может быть, а может и не быть установлен вашим портом. В любом случае будет создана символическая ссылка для объединения страниц Справочника foo(1) и alt-name(8).

# Глава 10. Порты, которым требуется Motif

Существует много приложений, которым для компиляции требуется библиотека Motif (которую можно приобрести у нескольких поставщиков, хотя есть и бесплатный клон в `x11-toolkits/lesstif`, о котором говорится, что с ним работает множество приложений). Так как это распространенный пакет и его лицензионное соглашение обычно позволяет распространение статически скомпонованных бинарных файлов, мы обратили особое внимание на работу с портами, которым требуется Motif, так чтобы мы могли легко создавать бинарные файлы, скомпонованные как динамически (для тех, кто строит приложение из порта), так и статически (для тех, кто будет распространять приложения в виде пакетов).

## 10.1. `USE_MOTIF`

Если вашему порту требуется Motif, задайте эту переменную в файле `Makefile`. Это не позволит людям, у которых нет собственной копии Motif, даже попытаться построить порт.

## 10.2. `MOTIFLIB`

Эта переменная будет установлена сценарием `bsd.port.mk` в соответствующее значение, соответствующее библиотеке Motif. Пожалуйста, измените исходные тексты вашего порта на использование этой переменной там, где упоминается библиотека Motif, в `Makefile` или `Imakefile`.

Могут быть два случая:

- Ели порт обращается к библиотеке Motif как `-lXm` в своих файлах `Makefile` или `Imakefile`, просто подставьте вместо этих обращений `${MOTIFLIB}`.

- Если порт использует `XmClientLibs` в своем файле `Imakefile`, измените это обращение на `${MOTIFLIB} ${XTOOLLIB} ${XLIB}`.

Заметьте, что переменная `MOTIFLIB` (как правило) раскрывается в `-L/usr/X11R6/lib -lXm` или `/usr/X11R6/lib/libXm.a`, так что нет нужды впереди добавлять `-L` или `-l`.

# Глава 11. Шрифты для X11

Если ваш порт устанавливает шрифты для X Window System, поместите их в каталог ``X11BASE`/lib/X11/fonts/local`. Этот каталог впервые появился в XFree86 3.3.3. Если он не существует, то, будьте добры, создайте его и выведите сообщение, обращающее внимание пользователя на необходимость обновить XFree86 до версии 3.3.3 или более новой, или по крайней мере добавить этот каталог к маршруту поиска шрифтов в файле `/etc/XF86Config`.

# Глава 12. Файлы в формате info

Если в вашем пакете нужна установка файлов GNU info, они должны быть перечислены в переменной `INFO` (без окончания `.info`), и тогда перед регистрации пакета во временный файл `pkg-plist` будет автоматически добавлен соответствующий код установки/удаления.

# Глава 13. Файлы `pkg-`*``

Есть несколько приёмов работы с файлами `pkg-`*``, которые мы ещё не описали, но они иногда могут быть очень кстати.

## 13.1. `pkg-message`

Если вам нужно вывести сообщение для человека, устанавливающего приложение, то вы можете поместить сообщение в файл `pkg-message`. Эта возможность часто оказывается полезной для вывода дополнительных шагов установки, которые нужно предпринять после выполнения команды pkg_add(1), или для вывода информации о лицензировании.

> Замечание: Файл `pkg-message` не нужно добавлять в `pkg-plist`. И он не будет автоматически выводиться, если пользователь использует порт, а не пакет, так что вы должны будете сами выводить его при выполнении цели `post-install`.

## 13.2. `pkg-install`

Если при установке бинарного пакета по команде pkg_add(1) вашему порту нужно выполнить какие-то дополнительные действия или команды, то вы можете сделать это с помощью скрипта `pkg-install`. Этот скрипт будет автоматически добавлен к пакету, и будет дважды запускаться по команде pkg_add(1): первый раз в виде `${SH} pkg-install ${PKGNAME} PRE-INSTALL`, а второй раз как `${SH} {PKGNAME} POST-INSTALL`. Для распознавания того, в каком режиме запущен скрипт, можно использовать параметр `$2`. Переменная окружения `PKG_PREFIX` будет принимать значение, соответствующее каталогу, в который устанавливается пакет. Дополнительная информация находится на странице Справочника о команде pkg_add(1).

> Замечание: Этот скрипт не запускается автоматически, если вы устанавливаете порт командой `make install`. Если же вам действительно необходимо его запустить, то запустите его явно из файла `Makefile` порта.

## 13.3. `pkg-deinstall`

Этот скрипт вызывается при удалении пакета.

Этот скрипт утилитой pkg_delete(1) будет запускаться дважды. Первый раз как `${SH} pkg-install ${PKGNAME} DEINSTALL`, а второй раз как `${SH} pkg-install ${PKGNAME} POST-DEINSTALL`.

## 13.4. `pkg-req`

Если вашему порту нужно определять, должен ли он устанавливаться или нет, то вы можете создать скрипт ``необходимости'' `pkg-req`. Он будет вызван автоматически в момент установки/удаления для определения того, должны ли они реально выполняться.

Скрипт будет запущен в процессе установки командой pkg_add(1), как `pkg-req ${PKGNAME} INSTALL`. В процессе удаления он будет запущен командой pkg_delete(1) как `pkg-req ${PKGNAME} DEINSTALL`.

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

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

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

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

    OCTAVE_VERSION= 2.0.13
    PLIST_SUB=  OCTAVE_VERSION=${OCTAVE_VERSION}

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

Эта подстановка (также, как и добавление любых справочных страниц) будет сделана между выполнением целей `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%%`, как описано выше. За исключением этого, имена из `PLIST_FILES` будут появляться в окончательном варианте перечня сборки без изменений, когда как `@dirrm` будет предшествовать именам из `PLIST_DIRS`. Для того, чтобы возыметь действие, `PLIST_FILES` и `PLIST_DIRS` должны задаваться до того, как будет записываться ``TMPPLIST``, то есть в цели `pre-install` или ещё раньше.

## 13.6. Изменение имён файлов `pkg-`*``

Все имена файлов `pkg-`*`` определяются с помощью переменных, так что вы можете изменить их, если это нужно, в вашем файле `Makefile`. Это особенно полезно, если вы используете одни и те же файлы `pkg-`*`` совместно между несколькими портами или пишете в один из вышеперечисленных файлов (в главе о записи в каталоги, отличные от `WRKDIR` объяснено, почему не рекомендуется осуществлять запись непосредственно в файлы `pkg-`*``.

Вот список имён переменных и их значений по умолчанию. (Значение `PKGDIR` по умолчанию равно `${MASTERDIR}`.)

Переменная | Значение по умолчанию
--- | ---
`DESCR` | `${PKGDIR}/pkg-descr`
`PLIST` | `${PKGDIR}/pkg-plist`
`PKGINSTALL` | `${PKGDIR}/pkg-install`
`PKGREQ` | `${PKGDIR}/pkg-req`
`PKGMESSAGE` | `${PKGDIR}/pkg-message`

Пожалуйста, изменяйте значения этих переменных, а не переопределяйте `PKG_ARGS`. Если вы измените значение переменных `PKG_ARGS`, то эти файлы при установке из порта будут установлены в каталог `/var/db/pkg` некорректно.

# Глава 14. Тестирование вашего порта

## 14.1. Запуск `make describe`

Некоторые утилиты FreeBSD для сопровождения портов, например, portupgrade(1), опираются на базу данных с именем `/usr/ports/INDEX`, в которой отслеживаются такие характеристики портов, как их зависимости. Файл `INDEX` создаётся при помощи `ports/Makefile` верхнего уровня по команде `make index`, спускающейся в подкаталог каждого порта и выполняющей в нём `make describe`. Таким образом, если выполнение `make describe` с каким-либо портом завершится неудачно, то никому не удастся создать `INDEX`, при этом много людей вскоре станут несчастны.

> Замечание: Возможность генерировать этот файл очень важна вне зависимости от того, какие параметры присутствуют в `make.conf`, поэтому, пожалуйста, избегайте, таких вещей, как использование декларации `.error`, когда (к примеру) требования к зависимость не было удовлетворено.

Пример 14-1. Как избегать использование `.error`

Предположим, что кто-то поместил строку

    USE_POINTYHAT=yes

в `make.conf`. Первый из последующих двух вариантов строк файла `Makefile` приведёт к неудачному завершению работы `make index`, а второй - нет:

    .if USE_POINTYHAT
    .error "POINTYHAT is not supported"
    .endif

    .if USE_POINTYHAT
    IGNORE=POINTYHAT is not supported
    .endif

Если команда `make describe` выдаёт строчку, а не ошибку, то для вас это пройдёт безболезненно. Обратитесь к файлу `bsd.port.mk`, чтобы выяснить значение выдаваемых строк.

Заметьте также, что запуск последней версии `portlint` (как указано в следующем разделе) приведёт к автоматическому запуску команды `make describe`.

## 14.2. Portlint

Проверьте свою работу командой `portlint` перед тем, как её отослать или перенести в дерево портов. `portlint` предупреждает вас о многих распространённых ошибках, как функциональных, так и стилистических. Для нового (или скопированного внутри хранилища) порта самым подходящим является запуск `portlint -A`; для уже существующего порта достаточно будет запустить `portlint -C`.

Так как для обнаружения ошибок `portlint` использует эвристические методы, то им могут выдаваться и ошибочные предупреждения. Кроме того, время от времени нечто, отмечаемое как некорректность, из-за ограничений механизма создания портов не может быть сделано никак иначе. Если вы сомневаетесь, то лучше всего спросить в Список рассылки, посвящённый Портам FreeBSD.

## 14.3. `PREFIX`

Попытайтесь сделать так, чтобы установка вашего порта осуществлялась относительно каталога `PREFIX`. (Значение этой переменной будет установлено в `LOCALBASE` (по умолчанию `/usr/local`), если только не заданы переменные `USE_X_PREFIX` или `USE_IMAKE`, в случае чего он будет принят равным `X11BASE` (по умолчанию `/usr/X11R6`).

Избежание явного указания `/usr/local` или `/usr/X11R6` в исходном коде сделает порт гораздо более гибким и способным удовлетворить потребности других серверов. Для портов, которые используют X, это происходит автоматически; в противном случае зачастую это может быть сделано простой заменой строк `/usr/local` (или `/usr/X11R6` для портов X, не использующих imake) в различных файлах `scripts/Makefile` порта на использование `${PREFIX}`, так как эта переменная автоматически передаётся далее на каждом этапе построения и установки.

Проверьте, что ваше приложение не устанавливает чего-либо в каталог `/usr/local` вместо `PREFIX`. Это можно быстро проверить следующим образом:

    # make clean; make package PREFIX=/var/tmp/port-name

Если что-то было установлено за пределами `PREFIX`, то процесс создания пакета сообщит об отсутствии файлов.

Здесь не проверяется ни наличие внешних ссылок, ни корректность использования `LOCALBASE` в качестве ссылки на файлы из других портов. Проверка установки в каталог `/var/tmp/`port-name`` делает это.

Не задавайте переменную `USE_X_PREFIX` до тех пор, пока она на самом деле не понадобится для порта (то есть он будет скомпонован с библиотеками X или нужно будет обращаться к файлам из `X11BASE`).

Переменная `PREFIX` может быть переназначена в вашем файле `Makefile` или в окружении пользователя. Однако строго не рекомендуется отдельным портам устанавливать эту переменную явно в файлах `Makefile`.

Кроме того, обратитесь к программам/файлам из других портов с переменными, перечисленными выше, без указания явных маршрутов. Например, если ваш порт требует, чтобы макро `PAGER` являлся полным путем утилиты `less`, используйте флаг компилятора:

    -DPAGER=\"${PREFIX}/bin/less\"

или

    -DPAGER=\"${LOCALBASE}/bin/less\"

если это порт X, вместо того, чтобы задавать `-DPAGER=\"/usr/local/bin/less\"`. Этот способ имеет больше шансов на работу, если системный администратор переместил всё дерево `/usr/local` куда-то в другое место.

# Глава 15. Обновление

Если вы заметите, что ваш порт устарел по сравнению с последней авторской версией, первым делом вы должны получить самую последнюю версия порта. Вы можете найти их в каталоге `ports/ports-current` на зеркальных FTP-серверах FreeBSD. Однако если вы работаете с достаточно большим количеством портов, наверное, будет проще использовать CVSup для поддержания всей коллекции портов в актуальном состоянии, как это описано в Руководстве. К тому же это даст возможность отслеживать все зависимости портов.

На следующем шаге необходимо выяснить, нет ожидает ли уже это обновление своей очереди. Для этого у вас есть две возможности. Существует интерфейс к базе данных сообщений о проблемах FreeBSD (PR) (известной также как `GNATS`) с поисковыми возможностями. Выберите из выпадающего списка `ports` и введите название порта.

Однако иногда люди забывают поместить название порта в поле Synopsis в точном виде. В таком случае вы можете воспользоваться Системой мониторинга портов FreeBSD (которая известна также как `portsmon`). В рамках этой системы делается попытка классифицировать PR, касающиеся портов, по имени порта. Для поиска PR, относящихся к определённому порту, используйте механизм Просмотра по одному порту.

Если таких отложенных PR не существует, то на следующем этапе следует послать сообщение электронной почты человеку, поддерживающему порт, который выдаётся по команде `make maintainer`. Этот человек может уже работать над обновлением, или иметь причину не обновлять порт прямо сейчас (например, из-за проблем со стабильностью функционирования новой версии); вам нет нужды дублировать их работу. Заметьте, что неподдерживаемые порты перечисляются с адресом мейнтейнера `ports@FreeBSD.org`, который является всего лишь адресом общего списка рассылки, так что отправка туда сообщений, скорее всего, в данном случае не поможет.

Если мейнтейнер просит вас выполнить обновление, либо или мейнтейнер отсутствует, то у вас появляется шанс помочь FreeBSD, приготовив обновление самим! Пожалуйста, внесите изменения и сохраните результат рекурсивного `diff` между новым и старым каталогами порта (например, если каталог с модифицированным портом называется `superedit`, а оригинальный, совпадающий с находящимся в нашем дереве портов, `superedit.bak`, то сохраните результат выполнения команды `diff -ruN superedit.bak superedit`). Подойдёт как унифицированный, так и контекстный дифф, однако коммиттеры портов обычно предпочитают унифицированный формат. Отметьте использование опции `-N`--это одобряемый способ заставить diff корректно работать в случае добавления новых файлов или удаления старых. Перед тем, как посылать нам diff-файл, пожалуйста, проверьте его, чтобы убедиться в значимости всех внесённых изменений. Для упрощения повторяющихся операций с файлами заплаток вы можете воспользоваться скриптом `/usr/ports/Tools/scripts/patchtool.py`. Перед тем, как его запускать, пожалуйста, прочтите `/usr/ports/Tools/scripts/README.patchtool`.

Если порт никем не поддерживается, а вы активно его используете, пожалуйста, подумайте над тем, чтобы добровольно стать его мейнтейнером. Во FreeBSD имеется более 2000 портов без поддержки, и это как раз та область, где всегда нужны добровольцы. (Детальное описание обязанностей мейнтейнеров можно найти в разделе MAINTAINER в Make-файлах.)

Лучше всего послать нам diff-файл, включив его в посылку по команде send-pr(1) (категория `ports`). Если вы добровольно собираетесь сопровождать порт, обязательно поместите текст `[maintainer update]` в начале строки описания и задайте в поле ``Class'' вашего PR строчку `maintainer-update`. В противном случае в поле ``Class'' вашего PR должно быть указано `change-request`. Будьте добры, в сообщении отметьте все добавленные или удалённые файлы, так как они будут непосредственно указаны cvs(1) при выполнении операции коммита. Если diff-файл имеет размер, превышающий 20КБ, сожмите его и обработайте утилитой uuencode; в противном случае просто включите его как есть в PR.

Прежде чем пользоваться send-pr(1) вы должны просмотреть раздел о Написании сообщений о проблемах в статье о Сообщениях об ошибках; он содержит гораздо больше информации о том, как писать полезные сообщения о проблемах.

> Важно: Если ваше обновление вызвано соображениями информационной безопасности или наличием серьёзных ошибок в имеющемся порте, пожалуйста, оповестите Группа Менеджеров Дерева Портов FreeBSD `<portmgr@FreeBSD.org>` о необходимости немедленного перепостроения и повторного распространения пакета вашего порта. В противном случае ничего не подозревающие пользователи pkg_add(1) будут продолжать устанавливать старую версию по команде `pkg_add -r` в течение ещё нескольких недель.

> Замечание: Повторяем еще раз - для посылки обновлений существующих портов используйте утилиту diff(1), а не shar(1)!

Теперь, когда вы проделали всё это, вам может понадобиться прочесть о том, как поддерживать актуальное состояние, в Гл. 19.

# Глава 16. Что делать нужно, и что делать нельзя

## 16.1. Введение

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

## 16.2. Удаление отладочной информации в бинарных файлах

Не удаляйте отладочную информацию из бинарных файлов вручную, если вы это делали. Во всех двоичных файлах отладочная информация должна быть удалена, и макрос `INSTALL_PROGRAM` будет выполнять установку и удаление отладочной информации одновременно (обратитесь к следующему разделу).

Если вам нужно удалить отладочную информацию из файла, но без использования макроса `INSTALL_PROGRAM`, то это можно сделать при помощи `${STRIP_CMD}`. Обычно это делается внутри цели `post-install`. К примеру:

    post-install:
        ${STRIP_CMD} ${PREFIX}/bin/xdl

Для проверки того, удалена ли отладочная информация из установленного выполнимого файла, выполните команду file(1). Если утилита не выдаст строку `not stripped`, то файл уже обработан. Кроме того, strip(1) не будет обрабатывать программу, отладочная информация из которой уже удалена; вместо этого утилита просто завершит свою работу.

## 16.3. Макросы INSTALL_*

Используйте макросы, которые есть в файле `bsd.port.mk` для обеспечения правильных прав доступа и владения файлов в своих целях `*-install`.

- `INSTALL_PROGRAM` - это команда для установки бинарных выполнимых файлов.

- `INSTALL_SCRIPT` - это команда для установки выполнимых скриптов.

- `INSTALL_DATA` - это команда для установки совместно используемых файлов данных.

- `INSTALL_MAN` - это команда для установки страниц Справочника и другой документации (никаких файлов она не сжимает).

В основе работы этих макросов лежит команда `install` со всеми соответствующими флагами. Смотрите пример их использования ниже.

## 16.4. `WRKDIR`

Не пишите ничего в файлы вне каталога `WRKDIR`. Каталог `WRKDIR` является единственным местом, которое гарантированно будет доступно для записи во время построения порта (обратитесь к главе о установке портов с CDROM за примером построения портов из дерева, доступного только для чтения). Если вам нужно изменить какой-либо из файлов `pkg-`*``, сделайте это, переопределив переменную, но не перезаписывая их.

## 16.5. `WRKDIRPREFIX`

Добейтесь того, чтобы ваш порт принимал во внимание значение переменной `WRKDIRPREFIX`. Большинство портов об этом не заботятся. В частности, если вы обращаетесь к каталогу `WRKDIR` другого порта, заметьте, что его правильным местоположением является ``WRKDIRPREFIX``PORTSDIR`/`subdir`/`name`/work` not ``PORTSDIR`/`subdir`/work` или ``.CURDIR`/../../`subdir`/`name`/work` или что-то подобное.

Кроме того, если вы сами задаете `WRKDIR`, то должны поставить перед ним знак `${WRKDIRPREFIX}${.CURDIR}`.

## 16.6. Различение операционных систем и версий ОС

Вы можете встретиться с кодом, который требует модификаций или условной компиляции в зависимости от того, с какой версией Unix он работает. Если вам нужно сделать такие изменения в коде для условной компиляции, то вы должны делать изменения как можно более общими, чтобы мы могли перенести код на более старые системы FreeBSD, а также и на другие системы BSD, такие, как 4.4BSD от CSRG, BSD/386, 386BSD, NetBSD, и OpenBSD.

Предпочтительным способом отделения кода для 4.3BSD/Reno (1990) и и более новых версий BSD является использование макроса `BSD`, определенного в файле `<sys/param.h>`. Хорошо, если этот файл уже включен; если это не так, то добавьте такой код:

    #if (defined(__unix__) || defined(unix)) && !defined(USG)
    #include <sys/param.h>
    #endif

в соответствующем месте файла `.c`. Мы надеемся, что все системы, в которых определены эти две константы, имеют файл `sys/param.h`. Если вы обнаружите систему, в которой это не так, мы хотим знать. Пошлите, пожалуйста, письмо на адрес Список рассылки, посвящённый Портам FreeBSD.

Другим способом является использование для этого стиля GNU Autoconf:

    #ifdef HAVE_SYS_PARAM_H
    #include <sys/param.h>
    #endif

Не забудьте добавить `-DHAVE_SYS_PARAM_H` к `CFLAGS` в файле `Makefile` при использовании этого метода.

Как только вы включите `sys/param.h`, то сможете воспользоваться следующим:

    #if (defined(BSD) && (BSD >= 199103))

для определения того, компилируется ли программа на основе кода Net2 версии 4.3 или более новой версии (например, FreeBSD 1.x, 4.3/Reno, NetBSD 0.9, 386BSD, BSD/386 1.1 и ниже).

Используйте:

    #if (defined(BSD) && (BSD >= 199306))

для определения того, компилируется ли программа на основе кода 4.4 или более новой (например, FreeBSD 2.x, 4.4, NetBSD 1.0, BSD/386 2.0 и выше).

Значение макроса `BSD` равно `199506` для кода на основе 4.4BSD-Lite2. Оно задано только для информационной целей. Оно не должно использоваться для различия между версиями FreeBSD, основанными на коде 4.4-Lite и версиями, в которые включены изменения из 4.4-Lite2. Вместо этого нужно использовать макрос `__FreeBSD__`.

Реже используйте:

- `__FreeBSD__` определён во всех версиях FreeBSD. Используйте его, если изменение, вносимое вами, касается только FreeBSD. Проблемы портирования, такие, как использование `sys_errlist[]` или `strerror()` являются особенностями систем BSD, а не FreeBSD.

- Во FreeBSD 2.x, значение `__FreeBSD__` определено как `2`. В более ранних версиях оно равно `1`. В более поздних версиях это значение всегда увеличивается в соответствии со старшим номером версии системы.

- Если вам нужно отделить системы FreeBSD 1.x от систем FreeBSD 2.x и более старших, правильным способом, как правило, будет использование макроса `BSD`, описанное выше. Если это действительно изменение, специфичное для FreeBSD (например, особая опция для динамической библиотеки при использовании `ld`), то для распознавания систем FreeBSD 2.x и более поздних нормальным будет использование `__FreeBSD__` и `#if __FreeBSD__ > 1`. Если вам нужно более точное определение версий FreeBSD, начиная с 2.0-RELEASE, то вы можете использовать следующее:

      #if __FreeBSD__ >= 2
      #include <osreldate.h>
      #    if __FreeBSD_version >= 199504
           /* 2.0.5+ release specific code here */
      #    endif
      #endif

Из сотен уже сделанных портов только в одном или двух случаях потребовалось использование `__FreeBSD__`. Если старые порты использовали этот макрос не по назначению, вовсе не значит, что вам нужно поступать точно также.

## 16.7. Значения __FreeBSD_version

Ниже для справки приводится перечень значений `__FreeBSD_version` в виде, который определён в `sys/param.h`:

Таблица 16-1. Значения __FreeBSD_version

Релиз | `__FreeBSD_version`
--- | ---
2.0-RELEASE | 119411
2.1-CURRENT | 199501, 199503
2.0.5-RELEASE | 199504
2.2-CURRENT до выхода 2.1 | 199508
2.1.0-RELEASE | 199511
2.2-CURRENT до выхода 2.1.5 | 199512
2.1.5-RELEASE | 199607
2.2-CURRENT до выхода 2.1.6 | 199608
2.1.6-RELEASE | 199612
2.1.7-RELEASE | 199612
2.2-RELEASE | 220000
2.2.1-RELEASE | 220000 (без изменений)
2.2-STABLE после выхода 2.2.1-RELEASE | 220000 (без изменений)
2.2-STABLE после включения texinfo-3.9 | 221001
2.2-STABLE после включения top | 221002
2.2.2-RELEASE | 222000
2.2-STABLE после выхода 2.2.2-RELEASE | 222001
2.2.5-RELEASE | 225000
2.2-STABLE после выхода 2.2.5-RELEASE | 225001
2.2-STABLE после появления ldconfig -R | 225002
2.2.6-RELEASE | 226000
2.2.7-RELEASE | 227000
2.2-STABLE после выхода 2.2.7-RELEASE | 227001
2.2-STABLE после изменения в semctl(2) | 227002
2.2.8-RELEASE | 228000
2.2-STABLE после выхода 2.2.8-RELEASE | 228001
3.0-CURRENT до изменения в mount(2) | 300000
3.0-CURRENT после изменения в mount(2) | 300001
3.0-CURRENT после изменения в semctl(2) | 300002
3.0-CURRENT после изменений в аргументах ioctl | 300003
3.0-CURRENT после перехода на формат ELF | 300004
3.0-RELEASE | 300005
3.0-CURRENT после выхода 3.0-RELEASE | 300006
3.0-STABLE после разбиения на ветки 3/4 | 300007
3.1-RELEASE | 310000
3.1-STABLE после выхода 3.1-RELEASE | 310001
3.1-STABLE после изменения в порядке следования конструкторов/деструкторов в C++ | 310002
3.2-RELEASE | 320000
3.2-STABLE | 320001
3.2-STABLE после несовместимых изменений в IPFW и сокетах | 320002
3.3-RELEASE | 330000
3.3-STABLE | 330001
3.3-STABLE после добавления mkstemp(3) в libc | 330002
3.4-RELEASE | 340000
3.4-STABLE | 340001
3.5-RELEASE | 350000
3.5-STABLE | 350001
4.0-CURRENT после появления ветки 3.4 | 400000
4.0-CURRENT после изменения в работе динамического компоновщика | 400001
4.0-CURRENT после изменения в порядке следования конструкторов/деструкторов в C++ | 400002
4.0-CURRENT после появления функции dladdr(3) | 400003
4.0-CURRENT после исправления ошибки в работе функции __deregister_frame_info динамического компоновщика (а также 4.0-CURRENT после интеграции EGCS 1.1.2) | 400004
4.0-CURRENT после изменения интерфейса функции suser(9) (а также 4.0-CURRENT после появления newbus) | 400005
4.0-CURRENT после изменения в регистрации cdevsw | 400006
4.0-CURRENT после добавления so_cred в проверки на уровне сокетов | 400007
4.0-CURRENT после добавления обработчика системного вызова poll в libc_r | 400008
4.0-CURRENT после перехода в ядре с типа `dev_t` на указатель `struct specinfo` | 400009
4.0-CURRENT после исправления дыры в безопасности jail(2) | 400010
4.0-CURRENT после изменения в типе данных `sigset_t` | 400011
4.0-CURRENT после перехода на компилятор GCC 2.95.2 | 400012
4.0-CURRENT после появления добавляемых обработчиков ioctl режима linux | 400013
4.0-CURRENT после заимствования OpenSSL | 400014
4.0-CURRENT после изменения в C++ ABI компилятора GCC 2.95.2 по умолчанию с -fvtable-thunks на -fno-vtable-thunks | 400015
4.0-CURRENT после заимствования OpenSSH | 400016
4.0-RELEASE | 400017
4.0-STABLE после появления 4.0-RELEASE | 400018
4.0-STABLE после появления отложенных контрольных сумм. | 400019
4.0-STABLE после интеграции кода библиотеки libxpg4 в libc. | 400020
4.0-STABLE после обновления пакета Binutils до версии 2.10.0, изменения в схеме пометки выполнимых файлов ELF и включения tcsh в качестве базового компонента. | 400021
4.1-RELEASE | 410000
4.1-STABLE после выхода 4.1-RELEASE | 410001
4.1-STABLE после переноса функции setproctitle(3) из библиотеки libutil в libc. | 410002
4.1.1-RELEASE | 411000
4.1.1-STABLE после выхода 4.1.1-RELEASE | 411001
4.2-RELEASE | 420000
4.2-STABLE после объединения libgcc.a и libgcc_r.a, а также соответствующих изменений в компоновке GCC. | 420001
4.3-RELEASE | 430000
4.3-STABLE после появления wint_t. | 430001
4.3-STABLE после добавления API состояния электропитания PCI. | 430002
4.4-RELEASE | 440000
4.4-STABLE после добавления d_thread_t. | 440001
4.4-STABLE после изменений в структуру для монтирования (это затрагивает KLD файловых систем). | 440002
4.4-STABLE после импортирования пользовательских компонент smbfs. | 440003
4.5-RELEASE | 450000
4.5-STABLE после переименования элементов структур usb | 450001
4.5-STABLE после того, как переменная rc.conf(5) `sendmail_enable` стала обрабатывать значение `NONE`. | 450004
4.5-STABLE после переключения на использование по умолчанию при построении пакетов XFree86 4. | 450005
4.5-STABLE после того, как сетевой фильтр для этапа подтверждения соединения был исправлен таким образом, что он больше не подвержен простым DoS-атакам. | 450006
4.6-RELEASE | 460000
Справочная страница по sendfile(2) в 4.6-STABLE приведена в соответствие с документацией, никакие заголовки не сравниваются с количеством данных, посланных из файла. | 460001
4.6.2-RELEASE | 460002
4.6-STABLE | 460100
4.6-STABLE после переноса из -CURRENT функциональности `sed -i'. | 460101
4.6-STABLE после MFC многих новых возможностей pkg_install из ветки HEAD. | 460102
4.7-RELEASE | 470000
4.7-STABLE | 470100
Начало генерации ссылок __std{in,out,err}p вместо __sF. Это переносит вычисление выражений в std{in,out,err} с момента компиляции на время выполнения. | 470101
4.7-STABLE после MFC изменений в mbuf для замены m_aux mbufs на m_tag's | 470102
В 4.7-STABLE появляется OpenSSL 0.9.7 | 470103
4.8-RELEASE | 480000
4.8-STABLE | 480100
4.8-STABLE после того, как функция realpath(3) была сделана совместимой с потоками выполнения | 480101
4.8-STABLE после изменений 3ware API в twe. | 480102
4.9-RELEASE | 490000
4.9-STABLE | 490100
4.9-STABLE после добавления e_sid в структуру kinfo_eproc. | 490101
4.9-STABLE после выполнения MFC функциональности libmap для rtld. | 490102
4.10-RELEASE | 491000
4.10-STABLE | 491100
5.0-CURRENT | 500000
5.0-CURRENT после добавления дополнительных полей в заголовке ELF и изменения метода пометки принадлежности к определённой системе для выполнимых файлов в формате ELF. | 500001
5.0-CURRENT после изменений в метаданных kld. | 500002
5.0-CURRENT после изменений buf/bio. | 500003
5.0-CURRENT после обновления binutils. | 500004
5.0-CURRENT после интеграции кода библиотеки libxpg4 в libc и появления интерфейса TASKQ. | 500005
5.0-CURRENT после добавления интерфейсов AGP. | 500006
5.0-CURRENT после обновления Perl до версии 5.6.0 | 500007
5.0-CURRENT после обновления кода KAME до версии 2000/07. | 500008
5.0-CURRENT после изменений в ether_ifattach() и ether_ifdetach(). | 500009
5.0-CURRENT после возврата в настройках утилиты mtree, применяемых по умолчанию, обратно к оригинальным и добавления флага -L для перехода по символическим ссылкам. | 500010
5.0-CURRENT после изменения в API для kqueue. | 500011
5.0-CURRENT после перемещения setproctitle(3) из библиотеки libutil в libc. | 500012
5.0-CURRENT после первого коммита SMPng. | 500013
5.0-CURRENT после переноса <sys/select.h> в <sys/selinfo.h>. | 500014
5.0-CURRENT после объединения libgcc.a и libgcc_r.a, а также соответствующих изменений в компоновке GCC. | 500015
5.0-CURRENT после изменения, позволяющего libc и libc_r быть скомпонованными вместе, что делает параметр -pthread ненужным. | 500016
5.0-CURRENT после перехода на использование struct xucred вместо struct ucred для стабилизации экспортируемого API ядра для mountd и т.д. | 500017
5.0-CURRENT после добавления переменной make CPUTYPE позволяющей контролировать специфичные для CPU оптимизации. | 500018
5.0-CURRENT после переноса machine/ioctl_fd.h в sys/fdcio.h | 500019
5.0-CURRENT после изменения имен для локализации. | 500020
5.0-CURRENT после импортирования Bzip2. Также означает удаление S/Key. | 500021
5.0-CURRENT с поддержкой SSE. | 500022
5.0-CURRENT после KSE Этап 2. | 500023
5.0-CURRENT после d_thread_t и переноса UUCP в порты. | 500024
5.0-CURRENT после изменения ABI из-за переноса передачи дескриптора и прав на 64-разрядные платформы. | 500025
5.0-CURRENT после перехода на использование по умолчанию XFree86 4 для построения пакетов и после добавления в библиотеку libc новой функции strnstr(). | 500026
5.0-CURRENT после добавления в библиотеку libc новой функции strcasestr(). | 500027
5.0-CURRENT после импорта пользовательских компонент smbfs. | 500028
5.0-CURRENT после добавления новых специфических для C99 целочисленных типов. | (Значение не изменено)
5.0-CURRENT после изменения возвращаемого функцией sendfile(2) значения. | 500029
5.0-CURRENT после добавления нового типа `fflags_t`, соответствующий файловым флагам. | 500030
5.0-CURRENT после переименования элементов структур usb. | 500031
5.0-CURRENT после обновления Perl до версии 5.6.1 | 500032
5.0-CURRENT после того как переменная rc.conf(5) `sendmail_enable` стала обрабатывать значение `NONE`. | 500033
5.0-CURRENT после добавления в функцию mtx_init() третьего параметра. | 500034
5.0-CURRENT после импорта Gcc 3.1 | 500035
5.0-CURRENT после удаления Perl из /usr/src | 500036
5.0-CURRENT после добавления функции dlfunc(3) | 500037
5.0-CURRENT после того, как были изменены типы некоторых записей в структуре sockbuf, а сама структура была реорганизована. | 500038
5.0-CURRENT после того, как в файлах заголовков было прекращено использование _BSD_FOO_T_ и начато использование _FOO_T_DECLARED. Это значение может быть также использовано как примерная точка начала поддержки пакетов в формате bzip2(1). | 500039
5.0-CURRENT после различных изменений в дисковых функциях, сделанных для избавления от зависимости от внутреннего устройства структуры метки диска. | 500040
5.0-CURRENT после добавления функции getopt_long(3) в библиотеку libc. | 500041
5.0-CURRENT после обновления Binutils 2.13, куда включена новая эмуляция FreeBSD, vec и формат выдачи. | 500042
5.0-CURRENT после добавления простых заглушек pthread_XXX к библиотеке libc, что сделало libXThrStub.so ненужной. 5.0-RELEASE. | 500043
5.0-CURRENT после создания ветки для RELENG_5_0 | 500100
<sys/dkstat.h> пуст и не должен использоваться. | 500101
5.0-CURRENT после изменения интерфейса d_mmap_t. | 500102
5.0-CURRENT после того, как было внесено изменение, при котором taskqueue_swi работает без Giant, и было добавлено taskqueue_swi_giant, работающее с Giant. | 500103
cdevsw_add() и cdevsw_remove() больше не существуют. Появилась технология выделения MAJOR_AUTO. | 500104
5.0-CURRENT после появления нового метода инициализации cdevsw. | 500105
devstat_add_entry() заменено на devstat_new_entry() | 500106
Изменение интерфейса devstat смотрите sys/sys/param.h 1.149 | 500107
Изменение в интерфейсе Token-Ring. | 500108
Добавление vm_paddr_t. | 500109
5.0-CURRENT после того, как функция realpath(3) была сделана совместимой с потоками выполнения | 500110
5.0-CURRENT после того, как функция usbhid(3) была приведена в соответствие с NetBSD | 500111
5.0-CURRENT после новой реализации NSS и добавления функций POSIX.1 getpw*_r и getgr*_r | 500112
5.0-CURRENT после удаления старой системы rc. | 500113
5.1-RELEASE. | 501000
5.1-CURRENT после появления ветки RELENG_5_1. | 501100
5.1-CURRENT после корректировки смысла функций sigtimedwait(2) и sigwaitinfo(2). | 501101
5.1-CURRENT после добавления полей lockfunc и lockfuncarg в bus_dma_tag_create(9). | 501102
5.1-CURRENT после интеграции снэпшота GCC 3.3.1-pre 20030711. | 501103
5.1-CURRENT осле изменений 3ware API в twe. | 501104
Поддержка в 5.1-CURRENT динамически скомпонованных /bin и /sbin, перемещение библиотек в /lib. | 501105
5.1-CURRENT после добавления в ядро поддержки Coda 6.x. | 501106
5.1-CURRENT после перемещения констант для 16550 UART из файла `<dev/sio/sioreg.h>` в `<dev/ic/ns16550.h>`. А также момент, когда rtld стал поддерживать функциональность libmap в безусловном режиме. | 501107
5.1-CURRENT после обновления в API PFIL_HOOKS | 501108
5.1-CURRENT после добавления функции kiconv(3) | 501109
5.1-CURRENT после изменений операций по умолчанию для open и close в cdevsw | 501110
5.1-CURRENT после изменений в структуре cdevsw | 501111
5.1-CURRENT после добавления множественного наследования для kobj | 501112
5.1-CURRENT после изменения if_xname в структуре ifnet | 501113
5.1-CURRENT после изменений, связанных с динамической компоновкой /bin и /sbin | 501114
5.2-RELEASE | 502000
5.2.1-RELEASE | 502010
5.2-CURRENT после отделения ветки RELENG_5_2 | 502100
5.2-CURRENT после добавления в libc функций __cxa_atexit/__cxa_finalize. | 502101
5.2-CURRENT после смены используемой по умолчанию библиотеки работы с потоками выполнения libc_r на libpthread. | 502102
5.2-CURRENT после большого изменения в API драйверов устройств. | 502103
5.2-CURRENT после добавления getopt_long_only(). | 502104
5.2-CURRENT после того, как макро переменная NULL была переопределена для языка C как ((void *)0), что привело к увеличению количества предупреждений компилятора. | 502105
5.2-CURRENT после установки и включения pf в процесс построения системы. | 502106
5.2-CURRENT после того, как значение time_t на платформе sparc64 стало 64-разрядным. | 502107
5.2-CURRENT после того, как поддержка компилятора Intel C/C++ в некоторых заголовочных файлах и execve(2) была изменена на более строго соответствующую POSIX. | 502108
5.2-CURRENT после введения программного интерфейса bus_alloc_resource_any | 502109
5.2-CURRENT после добавления поддержки локализации UTF-8 | 502110
5.2-CURRENT после удаления программного интерфейса getvfsent(3) | 502111
5.2-CURRENT после добавления директивы .warning для make. | 502112
5.2-CURRENT после того, как функция ttyioctl() стала обязательной для драйверов последовательных устройств. | 502113
5.2-CURRENT после импортирования ALTQ инфраструктуры. | 502114
5.2-CURRENT после того, как sema_timedwait(9) стал возвращать 0 в случае успеха и не нулевой код ошибки в случае неудачи. | 502115
5.2-CURRENT после того, как kernel тип dev_t стал указателем на struct cdev *. | 502116
5.2-CURRENT после того, как kernel тип udev_t изменился на dev_t. | 502117
5.2-CURRENT после добавления поддержки CLOCK_VIRTUAL и CLOCK_PROF в clock_gettime(2) и clock_getres(2). | 502118
5.2-CURRENT после того, как был проведён клонирующий пересмотр сетевого интерфейса. | 502119

> Замечание: Заметьте, что 2.2-STABLE иногда идентифицирует себя как ``2.2.5-STABLE'' после 2.2.5-RELEASE. Такой принцип использовался год и месяц, но мы решили изменить его на более однозначную систему нумерации старший/младший, начиная с версии 2.2. Это объясняется тем, что параллельная разработка в нескольких ветках делает непрактичным идентификацию релизов просто по их реальным датам выпуска. Если вы сейчас делаете порт, вам не стоит заботиться о старых версиях -CURRENT; они перечислены здесь просто в информационных целях.

## 16.8. Написание чего-либо после `bsd.port.mk`

Не пишите ничего после строки `.include <bsd.port.mk>`. Этой строки можно избежать, включив в где-то в середину вашего файла `Makefile` файл `bsd.port.pre.mk`, и файл `bsd.port.post.mk` в конец.

> Замечание: Вам нужно включить либо пару файлов `bsd.port.pre.mk`/`bsd.port.post.mk`, либо только `bsd.port.mk`; не используйте оба этих метода одновременно.

В файле `bsd.port.pre.mk` определяются лишь несколько переменных, которые могут быть использованы в тестах из файла `Makefile`, в файле `bsd.port.post.mk` заданы остальные.

Вот некоторые важные переменные, определенные в файле `bsd.port.pre.mk` (это не полный список, для выяснения полного списка прочтите, пожалуйста, сам файл `bsd.port.mk`).

Переменная | Описание
--- | ---
`ARCH` | Архитектура машины в виде, получаемом по команде `uname -m` (например, `i386`)
`OPSYS` | Тип операционной системы, получаемый по команде `uname -s` (например, `FreeBSD`)
`OSREL` | Версия релиза операционной системы (например, `2.1.5` или `2.2.7`)
`OSVERSION` | Версия операционной системы в виде числа, та же, что и `__FreeBSD_version`.
`PORTOBJFORMAT` | Формат объектных файлов, используемых в системе (`elf` или `aout`); заметьте, что для ``современных'' версий FreeBSD `aout` не используется.)
`LOCALBASE` | Корень дерева ``local'' (например, `/usr/local/`)
`X11BASE` | Корень дерева ``X11'' (например, `/usr/X11R6`)
`PREFIX` | Куда, собственно, устанавливается порт (обратитесь к подробной информации о `PREFIX`).

> Замечание: Если вы задаете переменные `USE_IMAKE`, `USE_X_PREFIX`, или `MASTERDIR`, то делайте это перед тем, как включать `bsd.port.pre.mk`.

Вот несколько примеров того, что вы можете написать после `bsd.port.pre.mk`:

    # no need to compile lang/perl5 if perl5 is already in system
    .if ${OSVERSION} > 300003
    BROKEN= perl is in system
    .endif

    # only one shlib version number for ELF
    .if ${PORTOBJFORMAT} == "elf"
    TCL_LIB_FILE=  ${TCL_LIB}.${SHLIB_MAJOR}
    .else
    TCL_LIB_FILE=  ${TCL_LIB}.${SHLIB_MAJOR}.${SHLIB_MINOR}
    .endif

    # software already makes link for ELF, but not for a.out
    post-install:
    .if ${PORTOBJFORMAT} == "aout"
           ${LN} -sf liblinpack.so.1.0 ${PREFIX}/lib/liblinpack.so
    .endif

Вы не забываете об использовании табуляции вместо пробелов после `BROKEN=` и `TCL_LIB_FILE=`, не так ли? :-).

## 16.9. Установка дополнительной документации

Если с вашим программным обеспечением поставляется некоторая документация, отличающаяся от стандартных страниц Справочника и файлов info, которая, как вы думаете, будет полезна пользователям, установите ее в каталог ``PREFIX`/share/doc`. Это может быть сделано, как и в предыдущем разделе, в цели `post-install`.

Создайте для вашего порта новый каталог. Имя каталога должно соответствовать тому, что представляет из себя порт. Обычно это означает `PORTNAME`. Однако, если вы думаете, что пользователь захочет иметь разные версии порта, установленные одновременно, то вы можете использовать полное имя `PKGNAME`.

Сделайте установку документации зависящей от переменной `NOPORTDOCS` для того, чтобы пользователи могли выключить это в файле `/etc/make.conf`, как здесь:

    post-install:
    .if !defined(NOPORTDOCS)
        ${MKDIR} ${DOCSDIR}
        ${INSTALL_MAN} ${WRKSRC}/docs/xvdocs.ps ${DOCSDIR}
     .endif

Вот несколько полезных переменных и то, как они преобразуются по умолчанию при использовании в `Makefile`:

- `DATADIR` преобразуется в ``PREFIX`/share/`PORTNAME``.

- `DOCSDIR` преобразуется в ``PREFIX`/share/doc/`PORTNAME``.

- `EXAMPLESDIR` преобразуется в ``PREFIX`/share/examples/`PORTNAME``.

Эти переменные экспортируются в `PLIST_SUB`. Их значения появятся там в виде имён путей относительно ``PREFIX``, если это возможно. То есть `share/doc/`PORTNAME`` в списке сборки по умолчанию будет заменен на `%%DOCSDIR%%`, и так далее. (Дополнительную информацию о подстановке в `pkg-plist` можно найти здесь.)

Все устанавливаемые файлы с документацией и каталоги должны быть перечислены в файле `pkg-plist` с префиксом `%%PORTDOCS%%`, например:

    %%PORTDOCS%%%%DOCSDIR%%/AUTHORS
    %%PORTDOCS%%%%DOCSDIR%%/CONTACT
    %%PORTDOCS%%@dirrm %%DOCSDIR%%

Кроме того, вы можете использовать файл `pkg-message` для вывода сообщений во время установки. За подробной информацией обратитесь к разделу об использовании `pkg-message`.

> Замечание: Файл `pkg-message` не нужно добавлять в `pkg-plist`.

В качестве альтернативы перечислению файлов документации в файле `pkg-plist`, порт может указать в переменной `PORTDOCS` список имён файлов и глобальных шаблонов командного процессора для добавления в окончательный список сборки. Имена будут задаваться относительно `DOCSDIR`. Таким образом, порт, использующий `PORTDOCS` и нестандартное местоположение документации, должен задавать соответствующим образом и `DOCSDIR`. Если каталог указан в `PORTDOCS` или соответствует шаблону для этой переменной, то полное поддерево с входящими в него файлами и каталогами будет регистрироваться в окончательном списке сборки. `PORTDOCS` не должна задаваться, если определена переменная `NOPORTDOCS`. Установка документации в `PORTDOCS`, как это показано выше, остаётся за самим портом. Типичный пример использования `PORTDOCS` выглядит следующим образом:

    .if !defined(NOPORTDOCS)
        PORTDOCS=   *
    .endif

## 16.10. Подкаталоги

Попробуйте поместить все файлы порта в правильных подкаталогах каталога `PREFIX`. Некоторые порты игнорируют все установки и помещают все в подкаталог с именем порта, что неправильно. Также многие порты помещают все, кроме бинарных файлов, файлов заголовков и страниц Справочника, в подкаталог каталога `lib`, что не очень хорошо работает с подходом BSD. Многие файлы должны быть перемещены в одно из следующих местоположений: `etc` (настроечные/конфигурационные файлы), `libexec` (выполнимые файлы, запускаемые из других программ), `sbin` (исполнимые файлы для администраторов/менеджеров системы), `info` (документация в формате info для просмотрщика info) или `share` (независимые от архитектуры файлы). Обратитесь к hier(7) для прояснения деталей; правила, покрывающие `/usr`, достаточно хорошо подходят также и к `/usr/local`. Исключением являются порты, имеющие дело с ``новостями'' USENET. Они могут использовать каталог ``PREFIX`/news` для установки своих файлов.

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

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

     :
    lib/X11/oneko/pixmaps/cat.xpm
    lib/X11/oneko/sounds/cat.au
     :
    @dirrm lib/X11/oneko/pixmaps
    @dirrm lib/X11/oneko/sounds
    @dirrm lib/X11/oneko

Однако иногда `@dirrm` будет выдавать ошибку, потому что другие порты тоже используют тот же самый подкаталог. Вы можете вызвать команду `rmdir` из `@unexec` для удаления без выдачи предупреждений только пустого каталога.

    @unexec rmdir %D/share/doc/gimp 2>/dev/null || true

Эта команда не выведет никаких сообщений об ошибках и не вызовет аварийного завершения работы pkg_delete(1), даже если каталог ``PREFIX`/share/doc/gimp` не пуст из-за того, что другие порты установили сюда какие-то файлы.

## 16.12. Идентификаторы UID

Если вашему порту требуется наличие некоторого пользователя в системе, на которую он устанавливается, пусть скрипт `pkg-install` вызовет команду `pw` для его автоматического создания. Посмотрите для примера на `net/cvsup-mirror`.

Если ваш порт должен использовать тот же самый идентификатор пользователя или группы при установке двоичного пакета, который был при компиляции, то вы должны выбрать свободный UID в диапазоне от 50 до 999 и зарегистрировать его ниже. Взгляните для примера на `japanese/Wnn6`.

Удостоверьтесь, что не используете UID, уже зарезервированный системой или другими портами.

Вот текущий перечень используемых UID между 50 и 999.

    bind:*:53:53:Bind Sandbox:/:/sbin/nologin
    majordom:*:54:54:Majordomo Pseudo User:/usr/local/majordomo:/nonexistent
    cyrus:*:60:60:the cyrus mail server:/nonexistent:/nonexistent
    gnats:*:61:1:GNATS database owner:/usr/local/share/gnats/gnats-db:/bin/sh
    proxy:*:62:62:Packet Filter pseudo-user:/nonexistent:/nonexistent
    uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/libexec/uucp/uucico
    xten:*:67:67:X-10 daemon:/usr/local/xten:/nonexistent
    pop:*:68:6:Post Office Owner (popper):/nonexistent:/sbin/nologin
    wnn:*:69:7:Wnn:/nonexistent:/nonexistent
    pgsql:*:70:70:PostgreSQL pseudo-user:/usr/local/pgsql:/bin/sh
    oracle:*:71:71::0:0:Oracle:/usr/local/oracle7:/sbin/nologin
    ircd:*:72:72:IRC daemon:/nonexistent:/nonexistent
    ircservices:*:73:73:IRC services:/nonexistent:/nonexistent
    ifmail:*:75:66:Ifmail user:/nonexistent:/nonexistent
    www:*:80:80:World Wide Web Owner:/nonexistent:/sbin/nologin
    alias:*:81:81:QMail user:/var/qmail/alias:/nonexistent
    qmaild:*:82:81:QMail user:/var/qmail:/nonexistent
    qmaill:*:83:81:QMail user:/var/qmail:/nonexistent
    qmailp:*:84:81:QMail user:/var/qmail:/nonexistent
    qmailq:*:85:82:QMail user:/var/qmail:/nonexistent
    qmailr:*:86:82:QMail user:/var/qmail:/nonexistent
    qmails:*:87:82:QMail user:/var/qmail:/nonexistent
    mysql:*:88:88:MySQL Daemon:/var/db/mysql:/sbin/nologin
    vpopmail:*:89:89:VPop Mail User:/usr/local/vpopmail:/nonexistent
    firebird:*:90:90:Firebird Database Administrator:/usr/local/firebird:/bin/sh
    mailman:*:91:91:Mailman User:/usr/local/mailman:/sbin/nologin
    gdm:*:92:92:GDM Sandbox:/:/sbin/nologin
    jabber:*:93:93:Jabber Daemon:/nonexistent:/nonexistent
    p4admin:*:94:94:Perforce admin:/usr/local/perforce:/sbin/nologin
    interch:*:95:95:Interchange user:/usr/local/interchange:/sbin/nologin
    squeuer:*:96:96:SQueuer Owner:/nonexistent:/bin/sh
    mud:*:97:97:MUD Owner:/usr/local/share/dgd:/bin/sh
    msql:*:98:98:mSQL-2 pseudo-user:/var/db/msqldb:/bin/sh
    rscsi:*:99:99:Remote SCSI:/usr/local/rscsi:/usr/local/sbin/rscsi
    squid:*:100:100:squid caching-proxy pseudo user:/usr/local/squid:/sbin/nologin
    quagga:*:101:101:Quagga route daemon pseudo user:/usr/local/etc/quagga:/sbin/nologin
    ganglia:*:102:102:Ganglia User:/nonexistent:/sbin/nologin
    sgeadmin:*:103:103:Sun Grid Engine Admin:/nonexistent:/sbin/nologin
    slimserv:*:104:104:Slim Devices SlimServer pseudo-user:/nonexistent:/sbin/nologin
    dnetc:*:105:105:distributed.net client and proxy pseudo-user:/nonexistent:/sbin/nologin
    clamav:*:106:106:Clamav Antivirus:/nonexistent:/sbin/nologin
    cacti:*:107:107:Cacti Sandbox:/nonexistent:/sbin/nologin
    fido:*:111:111:Fido System:/usr/local/fido:/bin/sh
    postfix:*:125:125:Postfix Mail System:/var/spool/postfix:/sbin/nologin
    rbldns:*:153:153:rbldnsd pseudo-user:/nonexistent:/sbin/nologin
    sfs:*:171:171:Self-Certifying File System:/nonexistent:/sbin/nologin
    agk:*:172:172:AquaGateKeeper:/nonexistent:/nonexistent
    moinmoin:*:192:192:MoinMoin User:/nonexistent:/sbin/nologin
    ldap:*:389:389:OpenLDAP Server:/nonexistent:/sbin/nologin
    drweb:*:426:426:Dr.Web Mail Scanner:/nonexistent:/sbin/nologin
    qtss:*:554:554:Darwin Streaming Server:/nonexistent:/sbin/nologin
    ircdru:*:555:555:Russian hybrid IRC server:/nonexistent:/bin/sh
    bacula:*:910:910:Bacula Daemon:/var/db/bacula:/sbin/nologin

Вот текущий перечень зарезервированных GID.

    bind:*:53:
    cyrus:*:60:
    proxy:*:62:
    authpf:*:63:
    uucp:*:66:
    dialer:*:68:
    network:*:69:
    pgsql:*:70:
    www:*:80:
    qnofiles:*:81:
    qmail:*:82:
    mailman:*:91:
    postfix:*:125:
    maildrop:*:126:
    rbldns:*:153:
    moinmoin:*:192:
    qtss:*:554:
    ircdru:*:555:

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

## 16.13. Поступайте разумно

Файл `Makefile` должен выполнять действия просто и небеспричинно. Если вы можете сделать что-то на несколько строк короче или более читабельно, сделайте это. В качестве примеров можно привести использование конструкций `.if` утилиты make вместо соответствующей конструкции `if` командного процессора, ненужность переопределения цели `do-extract` при возможности переопределения `EXTRACT*` и использование `GNU_CONFIGURE` вместо `CONFIGURE_ARGS+= --prefix=${PREFIX}`.

Если вы обнаружите, что для выполнения чего-то приходится писать много нового кода, то, пожалуйста, просмотрите файл `bsd.port.mk` на предмет того, не содержит ли он реализацию именно вашей проблемы. Хотя его трудно читать, имеется много проблем, выглядящих сложными, для которых файл `bsd.port.mk` уже содержит быстрое решение.

## 16.14. Работа как с `CC`, так и `CXX`

Порт должен принимать во внимание как переменную `CC`, так и `CXX`. Под этим мы подразумеваем, что порт ни в коем случае не должен устанавливать значения этих переменных, переопределяя имеющиеся значения; вместо этого от должен добавлять те значения, которые нужны, к имеющимся. Это нужно для того, чтобы параметры построения, относящиеся ко всем портам, могут быть заданы глобально.

Если порты не принимают во внимание значения этих переменных, пожалуйста, добавьте строку `NO_PACKAGE=ignores either cc or cxx` в файл `Makefile`.

Далее следует пример файла `Makefile`, использующего как переменную `CC`, так и `CXX`. Обратите внимание на использование символов `?=`:

    CC ?= gcc

    CXX ?= g++

Вот пример, в котором не принимаются во внимание ни переменная `CC`, ни `CXX`:

    CC = gcc

    CXX = g++

Обе переменные `CC` и `CFLAGS` могут быть определены в системах FreeBSD в файле `/etc/make.conf`. В первом примере задаётся значение, если оно ранее не было определено в `/etc/make.conf`, что сохраняет любые определения, данные на уровне системы в целом. Второй пример переопределяет всё, что было задано ранее.

## 16.15. Использование `CFLAGS`

Порт должен принимать во внимание переменную `CFLAGS`. Под этим мы подразумеваем, что порт ни в коем случае не должен устанавливать значения этих переменных, переопределяя имеющиеся значения; вместо этого от должен добавлять те значения, которые нужны, к имеющимся. Это нужно для того, чтобы параметры построения, относящиеся ко всем портам, могут быть заданы глобально.

Если он этого не делает, то, пожалуйста, добавьте в файл `Makefile` строчку `NO_PACKAGE=ignores cflags`.

Пример файла `Makefile`, в котором принимается во внимание переменная `CFLAGS`, приводится далее. Отметьте употребление символов `+=`:

    CFLAGS += -Wall -Werror

А вот пример, в котором не учитывается значение переменной `CFLAGS`:

    CFLAGS = -Wall -Werror

В системе FreeBSD переменная `CFLAGS` определена в файле `/etc/make.conf`. В первом примере к переменной `CFLAGS` добавляются дополнительные флаги, при этом сохраняются все определения, данные ранее на уровне системы. Во втором примере всё, что было задано ранее, игнорируется.

## 16.16. Конфигурационные файлы

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

Вместо этого установите файлы с примерами с неким расширением (``filename`.sample` подойдет) и выведите сообщение, указывающее на то, чтобы пользователь скопировал и отредактировал файл перед тем, как работать с программным обеспечением.

## 16.17. Пожелания

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

## 16.18. `README.html`

Не включайте сюда файл `README.html`. Этот файл не является частью дерева cvs, и он генерируется при помощи команды `make readme`.

## 16.19. Пометка порта как `BROKEN`, `FORBIDDEN` или как-то ещё

Рано или поздно, наступает момент, когда в некотором порте появляется уязвимость в информационной безопасности, либо он перестаёт работать и необходимы многие часы на тщательное исправление этого положения, либо он вообще устаревает, но по той или иной причине должен оставаться в дереве (и должен быть исправлен, правильно?). Для пометки порта как неработоспособного имеются три `make`-переменные, которые могут быть использованы в файле `Makefile` порта. Значение следующих `make`-переменных будут являться причинами, по которым порт помечен как неработоспособный, и выдаются пользователям. Пожалуйста, используйте корректные `make`-переменные, так как каждая переменная построения имеет абсолютно различный смысл как для пользователей, так и для автоматизированных систем, которые обрабатывают файлы `Makefile`.

- `BROKEN` предназначена для портов, которые не работают и не должны устанавливаться пользователями. Это предотвратит пользователей от установки порта.

- `TRYBROKEN` используется для портов, если вы пожелаете попытаться построить порт, помеченный, как `BROKEN`. Порты, помеченные, как `TRYBROKEN` также будут строиться Кластером Pointyhat.

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

- `IGNORE` предназначена для портов, которые по той или иной причине не должны строиться. Пользователи и кластер Pointyhat не будут, ни при каких условиях, строить порты, помеченные как `IGNORE`. Если вы сомневаетесь, используйте `IGNORE`, если хотите избежать построения порта.

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

## 16.20. Необходимые предосторожности

Иногда бывает необходимо обходить ошибки в программном обеспечении, которым комплектовались предыдущие версии FreeBSD.

- Некоторые версии make(1) (по крайней мере в версиях 4.8 и 5.0) неправильно отрабатывали сравнение на основе `OSVERSION`. Это часто приводило к ошибкам при выполнении команды `make describe` (и, в свою очередь, в целом при выполнении `make index` для портов). Эта ситуация обходится окружением условной операции сравнения пробелами, например:

      if ( ${OSVERSION} > 500023 )

  Учтите, что при тестовой установке порта на 4.9 или 5.2 эта проблемы не обнаруживается.

## 16.21. Разное

Файлы `pkg-descr` и `pkg-plist` должны проверяться дважды. Если вы пересматриваете порт и думаете, что его можно описать иначе, сделайте это.

Пожалуйста, не создавайте дополнительных копий лицензии GNU General Public License в нашей системе.

Будьте внимательны с юридическими вопросами! Не делайте из нас нелегальных распространителей ПО!

## 16.22. Если вы испытываете затруднения...

Посмотрите существующие примеры и файл `bsd.port.mk` перед тем, как задавать нам вопросы! ;-)

Задавайте нам вопросы, если у вас появились проблемы! Не бейтесь головой об стену! :-)

# Глава 17. Примерный `Makefile`

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

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

    [заголовок...просто чтобы нам было легче идентифицировать порт.]
    # New ports collection makefile for:   xdvi
    [строчка "version required" необходима только тогда, когда переменная
    PORTVERSION недостаточно конкретна для описания порта.]
    # Date created:            26 May 1995
    [Это человек, который сделал первоначальный порт для FreeBSD, в частности,
    тот, кто создал первую версию этого файла Makefile.  Запомните, что позже
    при обновлении порта эта строка меняться не должна.]
    # Whom:                Satoshi Asami <asami@FreeBSD.org>
    #
    # $FreeBSD$
    [ ^^^^^^^^^ Эта строка будет автоматически заменена со строчкой RCS ID
    системой CVS при выполнении операции коммита в наше хранилище.  При
    обновлении порта не приводите эту строку обратно к виду
    "$FreeBSD$".  CVS сделает все автоматически.]
    #

    [секция описания собственно порта и основного сервера - сначала всегда
     PORTNAME и PORTVERSIONA, за ним следует CATEGORIES, а затем
     MASTER_SITES, за которым может идти MASTER_SITE_SUBDIR.
     PKGNAMEPREFIX и PKGNAMESUFFIX, если они нужны, следуют за ними.
     Затем следует DISTNAME, EXTRACT_SUFX и/или DISTFILES, а потом, если это нужно,
     EXTRACT_ONLY.]
    PORTNAME=      xdvi
    PORTVERSION=   18.2.]
    CATEGORIES=    print
    [не забывайте лидирующий слэш ("/")!
     если вы не используете макросы MASTER_SITE_*]
    MASTER_SITES=  ${MASTER_SITE_XCONTRIB}
    MASTER_SITE_SUBDIR= applications
    PKGNAMEPREFIX= ja-
    DISTNAME=      xdvi-pl18
    [задайте это, если исходный код поставляется не в виде
     стандартного файла ".tar.gz"]
    EXTRACT_SUFX=  .tar.Z

    [секция патчей -- может быть пустой]
    PATCH_SITES=   ftp://ftp.sra.co.jp/pub/X11/japanese/
    PATCHFILES=    xdvi-18.patch1.gz xdvi-18.patch2.gz

    [сопровождающий; *обязательное поле*!  Это человек (предпочтительно с
     привилегиями на операцию коммита), с которым может связаться пользователь
     для получения ответов на вопросы и посылки сообщений об ошибках - этот
     человек должен быть создателем порта или кем-то, кто может передать
     вопросы создателю порта.  Если вы на самом деле не хотите указывать здесь
     свой адрес, задайте здесь "ports@FreeBSD.org".]
    MAINTAINER=    asami@FreeBSD.org
    COMMENT=       A DVI Previewer for the X Window System

    [зависимости -- могут быть пустыми]
    RUN_DEPENDS=   gs:${PORTSDIR}/print/ghostscript
    LIB_DEPENDS=   Xpm.5:${PORTSDIR}/graphics/xpm

    [этот раздел для остальных стандартных переменных из bsd.port.mk, кроме
     тех, что перечислены выше]
    [Если порт задает вопросы во время этапов настройки, построения,
     установки...]
    IS_INTERACTIVE=        yes
    [Если распаковка происходит в каталог, отличных от ${DISTNAME}...]
    WRKSRC=            ${WRKDIR}/xdvi-new
    [Если патчи делались не относительно ${WRKSRC}, вам, может быть, не
     придется изменять эту переменную]
    PATCH_DIST_STRIP=      -p1
    [Если порт требует скрипта "configure", генерируемого GNU-версией программы
     autoconf]
    GNU_CONFIGURE= yes
    [Если для построения порту требуется GNU-версия утилиты make, а не
     /usr/bin/make...]
    USE_GMAKE=     yes
    [Если это приложение X и требует запуска "xmkmf -a"...]
    USE_IMAKE=     yes
    [и так далее]

    [В правилах ниже используются нестандартные переменные]
    MY_FAVORITE_RESPONSE=  "yeah, right"

    [теперь специальные правила, в порядке их вызова]
    pre-fetch:
        я что-то выкачиваю, точно

    post-patch:
        мне кое-что сделать после применения патча, великолепно

    pre-install:
        и потом еще кое-что перед установкой, ого

    [и, наконец, эпилог]
    .include <bsd.port.mk>

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

Первым делом убедитесь, что ваш порт практически полностью завершён, осталось только создать `pkg-plist`.

Затем временное дерево каталогов, куда может быть установлен ваш порт, и установите все зависимости. `port-type` должен быть `local` для не-X портов, `x11-4` или `x11` для портов, которые устанавливаются в иерархию каталогов XFree86 4 или более раннего релиза XFree86, соответственно.

    ># mkdir /var/tmp/port-name
    # mtree -U -f /etc/mtree/BSD.port-type.dist -d -e -p /var/tmp/port-name
    # make depends PREFIX=/var/tmp/port-name

Сохраните структуру каталогов в новом файле.

    # (cd /var/tmp/port-name && find -d * -type d) | sort > OLD-DIRS

Создайте пустой файл `pkg-plist`:

    # touch pkg-plist

Если ваш порт принимает во внимание `PREFIX` (а он должен это делать), то тогда вы можете установить порт и создать список упаковки.

    # make install PREFIX=/var/tmp/port-name
    # (cd /var/tmp/port-name && find -d * \! -type d) | sort > pkg-plist

Кроме того, в список упаковки вы должны добавить все вновь созданные каталоги.

    # (cd /var/tmp/port-name && find -d * -type d) | sort | comm -13 OLD-DIRS - | sort -r | sed -e 's#^#@dirrm #' >> pkg-plist

И наконец, вам нужно вручную отшлифовать список упаковки; его создание автоматизировано не полностью. Страницы справочной системы должны быть перечислены в файле `Makefile` порта в переменных `MAN`n``, а не в списке упаковки. Пользовательские конфигурационные файлы должны быть удалены или быть установлены как ``filename`.sample`. Файл `info/dir` включать в список не нужно, но должны быть добавлены соответствующие строчки `install-info`, так, как это описано в разделе о файлах в формате info. Все библиотеки, устанавливаемые портом, должны быть перечислены так, как это описано в разделе о динамических библиотеках.

Как альтернативу, можно использовать скрипт `plist` из `/usr/ports/Tools/scripts/` для автоматического построения списка упаковки.

# Глава 19. Актуализация

Коллекция Портов FreeBSD постоянно изменяется. Здесь находится некоторая информация о том, как поддерживать её в актуальном состоянии.

## 19.1. FreshPorts

Самым простым способом отслеживать уже произошедшие обновления является подписка на FreshPorts. Для мониторинга вы можете выбрать несколько портов. Мейнтейнерам настоятельно рекомендуется подписаться здесь, потому что они будут получать уведомления не только о собственных изменениях, но и об изменениях, сделанных любым другим коммиттером FreeBSD. (Это часто необходимо для синхронизации с изменениями на более низком технологическом уровне--хотя более корректным было бы получение предупреждений от тех, кто вносит подобные изменения, иногда этот этап пропускается или он просто непрактичен. Кроме того, в некоторых случаях изменения по своей природе весьма незначительны. Мы полагаем, что любой разработчик в таких ситуациях будет руководствоваться здравым смыслом).

Если вы хотите использовать FreshPorts, то вам нужна только учётная запись. Если регистрационный адрес вашей электронной почты будет иметь вид `@FreeBSD.org`, то справа на Web-страницах вы увидите дополнительную ссылку. Для тех из вас, кто уже получил учётную запись FreshPorts, но не использовал собственный адрес электронной почты `@FreeBSD.org`, достаточно сменить адрес на `@FreeBSD.org`, подписаться, а затем сменить его обратно.

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

## 19.2. Web-интерфейс к хранилищу исходных текстов

Файлы в хранилище исходных текстов можно просматривать при помощи Web-интерфейса. Изменения, которые касаются в целом всей системы портов, теперь документируются в файле CHANGES. Изменения, касающиеся отдельных портов, отражаются теперь в файле UPDATING. Однако однозначный ответ на любой вопрос можно найти, только прочитав исходных код bsd.port.mk и связанных с ним файлов.

## 19.3. Список рассылки FreeBSD, посвящённый портам

Если вы поддерживаете порты, то должны следить за Список рассылки, посвящённый Портам FreeBSD. О важных изменениях, отражающихся на работе портов, будет сообщаться здесь, а затем они переносятся в `CHANGES`.

## 19.4. Кластер построения портов FreeBSD

Одной из наименее известных сильных сторон FreeBSD является тот факт, что для непрерывного построения Коллекции Портов для каждого из основных релизов ОС для каждой архитектуры уровня поддержки Tier-1 выделен целый кластер машин. Вы можете увидеть результаты этих построений в протоколах построения пакетов и обнаруженных ошибок.

## 19.5. Проверка дистрибутивных файлов портов FreeBSD

Кластер построения выделен для выполнения самого последнего релиза каждого из портов, дистрибутивный файл которых уже был сгружен. Однако из-за постоянных изменений в Internet, дистрибутивные файлы быстро исчезают. Средство инспектирования дистрибутивных файлов FreeBSD пытается опросить каждый из сайтов, доступный для сгрузки каждого из портов для определения того, доступны ли ещё дистрибутивные файлы. Мейнтейнеры должны периодически просматривать этот протокол, и не только для ускорения процесса построения пользователем, но и для избежания траты пропускной способности сайтов, на которых все эти дистрибутивные файлы размещаются на добровольной основе.

## 19.6. Система мониторинга портов FreeBSD

Другим полезным ресурсом является Система мониторинга портов FreeBSD (известная также как `portsmon`). Система представляет собой базу данных, обрабатывающую информацию из нескольких источников и позволяющую просматривать их при помощи Web-интерфейса. На данный момент задействованы база сообщений об ошибках (PR), протоколы ошибок кластера построения и отдельные файлы из коллекции портов. В будущем в этот список будет добавлена система проверки дистрибутивных файлов и другие ресурсы.

Для начала вы можете просмотреть всю информацию о некотором порте при помощи средства Просмотра отдельных портов.

По вопросам связанным с системой портов для FreeBSD, пишите по адресу <ports@FreeBSD.org>.
По вопросам, связанным с этой документацией, пишите по адресу <doc@FreeBSD.org>.