Рашид Ачилов
Создаем порт для FreeBSD своими руками
Часть II: расширенные возможности

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

Расширенные возможности системы

   Скромный размер нашего первого порта и его достаточная простота не позволила нам рассмотреть все возможности системы портов. В этом опять же проявляется ее достоинство – не нужно знать много для построения сравнительно простого порта. Но зачастую бывает так, что необходимо реализовать некую собственную функцию по обработке исходного текста или проверить наличие некоторой программы до начала установки своей. Сразу же возникает вопрос – пытаться реализовать это своими силами или же это уже было кем-то когда-то реализовано?
   Расширенные возможности системы сборки портов, которые мы не использовали в первой части и которые можно использовать, это:
   • Многофайловые дистрибутивы с возможностью отбора файлов в зависимости от заданного набора переменных.
   • Внешние патчи, которые можно подключать в зависимости от заданного набора переменных.
   • Задание параметров сборки порта с помощью полноэкранного текстового режима OPTIONS, с возможностью дальнейшего хранения и редактирования этих параметров.
   • Дополнение или замена части процедур создания программы из порта.
   Возможность работы с многофайловыми дистрибутивами позволяет указать, с какого из перечисленных сайтов нужно загружать указанный файл. Допустим, программа состоит из файлов file1.tgz и file2.tgz. File1.tgz присутствует только на двадцатом из перечисленных MASTER_SITES, в то время как file2.tgz – всюду. Система будет попусту обшаривать девятнадцать сайтов. Это не страшно, когда делается автоматом, но ужасно нервирует, когда спешишь. Кроме того, в зависимости от заданного набора параметров можно включать или исключать некоторые компоненты. Это особенно существенно, когда эти компоненты весят десятки мегабайт (например, порт editors/openoffice2).
   Работа с внешними патчами также крайне важна, особенно когда автор программы не желает контактировать и исправлять код. В таком случае патч либо размещается непосредственно в дереве портов, либо (как правило, если он довольно объемный) выкладывается на некоторый сайт и указывается с помощью PATCH_SITES.
   Задание параметров сборки порта значительно повышает удобство работы с ним. Многие порты имеют не один десяток переменных «WITH_FOO=yes WITHOUT_BAR=yes», которые не то, что набрать в командной строке – запомнить непросто! Например, порт graphics/ImageMagick имеет 26 переменных типа «WITHOUT_IMAGEMAGICK_SOME=yes». Если бы автор порта сделал экран опций, работать с таким портом было бы гораздо проще.
   Дополнение или замена части процедур создания порта – это крайне важные возможности системы. Перечень основных шагов системы, выполняемых при создании программы, был уже приведен в [1]. Но возможно ли, скажем, установить через систему портов бесплатную программу с закрытым исходным текстом? Думаете, нет? Можно. И именно для этого были реализованы механизмы дополнения и/или замены части процедур сборки порта. Мы рассмотрим их в соответствующем разделе.
   А теперь пора перейти от слов к делу.

www.foobar.comнаходится за рубежом, имеет быстрый и надежный канал. www.nichego.net находится в г. Тьмутаракани и подключен к Интернету через модем на 28.8 кБит. Как сделать так, чтобы система брала только file1.tar.gz с www.nichego.net, а остальные – с www.foobar.com? Нужно ассоциировать метки и с файлами, и с сайтами:
 
   DISTFILES= file1.tar.bz2 \
   file2.tar.bz2:foobar \
   file3.tar.bz2:foobar
   MASTER_SITES= http://www.foobar.com/:foobar \
    http://www.nichego.net
 
   Если метка отсутствует, считается, что файл (сайт) имеет метку по умолчанию DEFAULT. Явно задавать ее не следует, разве что требуется перечислить несколько групп и DEFAULT в том числе. Система свяжет DISTFILES и MASTER_SITES, используя метки, и загрузит файлы в следующей последовательности: сначала file1.tar.bz2 с http://www.nichego.net, потом file2.tar.bz2 и file3.tar.bz2 с http://www.foobar.com.
   Можно было бы сделать, чтобы и файл file1.tar.bz2 тоже сначала проверялся на http://www.foobar.com, а уже потом – на http://www.nichego.net. Для этого нужно www.foobar.comвключить также и в группу DEFAULT:
 
   MASTER_SITES= http://www.foobar.com/:foobar,DEFAULT
 
   Один и тот же файл может входить в несколько групп. Равным образом в одну группу могут входить несколько файлов. Естественно, допускается использование подстановки переменных:
 
   GSI_VERSION= 2005-01-20
   DISTFILES+= gsi-$(GSI_VERSION)-sorted.txt.bz2:oorus,oorus2
   INFRA_PATCHEXT= OOo_1.1.4_infra_patches
   DISTFILES+= ${INFRA_PATCHEXT}.tar.gz:DEFAULT,oorus
   MASTER_SITES+= http://ootrans.i-rs.ru/out/:oorus
   MASTER_SITES+= ftp://ftp.i-rs.ru/pub/openoffice/1.1.4/ru/:oorus2
   MASTER_SITES+= ftp://ftp/granch.ru/pub/openoffice
 
   В данном фрагменте файл gsi-2005-01-20-sorted.txt.bz2 будет скачиваться сначала с http://ootrans.i-rs.ru/out, потом с ftp://ftp.i-rs.ru/pub/openoffice/1.1.4/ru, а файл OOo_1.1.4_infra_patches.tar.gz – сначала с ftp://ftp.i-rs.ru/pub/openoffice/1.1.4/ru, потом с ftp://ftp.granch.ru/pub/openoffice.
   Когда стоит пользоваться такой возможностью? Когда порт может состоять из большого количества файлов и хочется сделать возможность обойтись без загрузки файлов, которые не нужны.
   Например, это не было сделано в порту editors/openoffice-1.1, и в результате чего исходные тексты Mozilla Suite (обьема немалого – 35 Мб) загружались независимо от желания пользователя ее использовать.
   Использование внешних патчей во многом похоже на загрузку файлов исходного кода программы, только здесь используются переменные PATCH_SITES и PATCHFILES:
 
   PATCH_SITES= ftp://ftp.cis.upenn.edu/pub/xv/
   PATCHFILES= ${DISTNAME}.JPEG-patch ${DISTNAME}.TIFF-patch \
   croppad.patch grabpatch vispatch \
   deepcolor.patch gifpatch exceed_grab.patch \
   tiff1200.patch gssafer.patch
 
   Имейте в виду, что патчи, заданные в PATCHFILES, применяются до применения патчей из подкаталога files! То есть последовательность действий будет выглядеть так:
 
   ===> Patching for xv-3.10a_5
   ===> xv-3.10a_5 depends on file: /usr/local/bin/perl5.8.7 - found
   ===> Applying distribution patches for xv-3.10a_5
   ===> Applying FreeBSD patches for xv-3.10a_5
 
   Когда стоит использовать внешние патчи? Разработчики обычно используют их, чтобы избежать выпуска нового релиза программы (так обычно поступают разработчики Squid – вместо выпуска нового релиза они выкладывают патчи значительного обьема), авторы портов, не являющиеся разработчиками программы, – чтобы внести в исходный текст изменения, с которыми автор может быть не согласен, если они достаточно обьемные и их нельзя поместить непосредственно в дерево портов, для расширения функциональности и т. д.
   Следует учесть то, что если патч не создан с использованием стандартной процедуры diff, то его нельзя применять описанным методом и необходимо предусмотреть для него специальную обработку (см. пример в описании порта для OpenOffice).

Опции

   Если программа сложная, то, как правило она предлагает множество различных вариантов построения – с использованием такой-то возможности, без использования такой-то возможности... Некоторые порты сначала проводят «автоматическое обнаружение» некоторых задействуемых компонент, а уже потом устанавливают переменные, включающие или отключающие различные возможности, а некоторые оставляют это на усмотрение пользователя. Если пользователь об этом не подозревает, то он может так никогда ими и не воспользоваться. Одним из примеров того, как делать ни в коем случае не надо, я считаю порт graphics/ImageMagick. Мало того, что там 26 переменных, так еще пользователь даже не оповещается, что они вообще есть!
 
 
    Рисунок 1.Появилась возможность задавать опции в полноэкранном текстовом режиме
   В результате строка запуска сборки порта может выглядеть, например,таким образом:
 
   # make WITHOUT_IMAGEMAGICK_JPEG=yes WITH_WINDOWS_FONT_DIR=/tmp/blabla WITHOUT_IMAGEMAGICK_PNG=yes WITHOUT_IMAGEMAGICK_BZIP2=yes ...
 
   Кроме того, что это просто очень долго набирать, попробуйте-ка вспомнить, какие там опции задавались при предыдущей сборке полгода назад? Разумеется, это крайне неудобно, и некоторое время назад в системе появилась возможность задавать опции в полноэкранном текстовом режиме (см. рис. 1).
   Все опции, перечисленные на экране, задаются и отменяются простым нажатием пробела, результат выбора будет сохранен и использован при последующих сборках порта. В любое время его можно изменить, выполнив команду:
 
   # make config
 
   Формируется экран опций следующей командой в Makefile:
 
   OPTIONS= LDAP "With LDAP support" on \
   ADS "With Active Directory support" off \
   CUPS "With CUPS printing support" on \
   WINBIND "With WinBIND support" on \
   ACL_SUPPORT "With ACL support" off \
   SAM_XML "SAM with XML support" off
 
 
   Первый параметр задает имя опции, которое потом будет использовано в переменной WITH_*. Например, для первого параметра имя переменной будет WITH_LDAP. Второй параметр задает текст комментария, который будет выведен справа от соответствующей опции, и третий – значение по умолчанию. При указании «on» опция по умолчанию включена, при указании «off» – выключена.
   Хорошо, опции заданы. Как их обработать?
   Прежде всего необходимо отметить, что при использовании OPTIONS включение файла bsd.port.mk следует заменить на:
 
   .include <bsd.port.pre.mk>
   # processing WITH_SOMEWHERE here
   .include <bsd.port.post.mk>
 
   иначе ни одна переменная WITH_SOMEWHERE распознана не будет. Обработка же переменных выполняется стандартным образом – с помощью условия if задаются дополнительные параметры для configure, зависимости, подстановки для pkg-plist и т. д.
 
   .if defined(WITH_SAM_XML)
   LIB_DEPENDS+= xml2.5:${PORTSDIR}/textproc/libxml2
   CONFIGURE_ARGS+= --with-xml-prefix=${LOCALBASE}
   WANT_EXPSAM_MODULES+= xml
   PLIST_SUB+= SAMXML=""
   .else
   PLIST_SUB+= SAMXML="@comment "
   .endif
 
   Комбинация проверяемых условий может быть довольно сложной. В качестве примера того, как могут использоваться значения опции, лучше всего рассматривать порт net/samba3 – в нем очень много опций, есть на что посмотреть.
   Ну и наконец самый интересный раздел – замена/дополнение стандартных обработчиков Makefile при сборке порта. Как уже было сказано в [1], сборка порта состоит из последовательности выполнения ряда мишеней, которые в свою очередь делятся на подмишени pre-something, do-something и post-something (есть еще специальные мишени, описание их см .в bsd.port.mk). Для чего это было сделано? Для того чтобы иметь возможность воздействия на процесс создания порта – что-нибудь изменить, вывести сообщение, создать файл или каталог и т. д. Как следует из названия, подмишени pre-somethnig и post-something выполняются соответственно до и после мишени something. Например, последовательность распаковки будет такова: pre-extract, do-extract, post-extract. При этом, если подмишень do-something не описана, будет выполняться стандартная системная обработка. Обратите внимание, что, если мишень do-something описана, она замещает стандартную мишень и вся ответственность за выполнение данного шага ложится на майнтайнера порта, то есть, например, даже если в Makefile, идущем с программой, есть мишень install, то при наличии в Makefile порта подмишени do-install мишень install из Makefile программы не будет выполнена никогда!
   Дополнение стандартных мишеней очень широко используется для вывода различных сообщений в процессе сборки порта, создания каких-либо файлов и т. д. Например:
 
   pre-extract:
   @${ECHO_MSG} ""
   @${ECHO_MSG} "For debugging information support you should specify"
   @${ECHO_MSG} "WITH_DEBUG=yes (press Ctrl-C here and start make WITH_DEBUG=yes)"
   @${ECHO_MSG} ""
   @sleep 2
   post-deinstall:
   @${ECHO_MSG} ""
   @${ECHO_MSG} "Do not forget delete filter description from /etc/mail/freebsd.mc"
   @${ECHO_MSG} "and rebuild sendmail.cf file!"
   @${ECHO_MSG} ""
   pre-configure:
   .if defined(WITHOUT_RC_NG)
   @${SED} -e "s=%%PREFIX%%=${PREFIX}=" ${FILESDIR}/milter-sid.sh \
   > ${WRKSRC}/milter-sid.sh
   .endif
 
   Заменять обработчики мишеней (создавать секции do-something) [2]не рекомендует, но тем не менее это единственный путь для установки программ с закрытым исходным кодом, а также скриптов и программ, упакованных нестандартным образом. Например, мне встречалась программа, дистрибутив которой был упакован в архив формата ZIP, внутри котрого находился архив .tar.bz2 и файл сигнатуры .sig. Для распаковки нужно было сначала распаковать архив ZIP, потом проверить сигнатуру, а только потом – распаковывать .tar.bz2.
   Но довольно теории. Рассмотрим в качестве примеров два порта, которые были мной созданы в разное время – порт для скрипта монтирования сетевых ресурсов Windows при входе в систему mountsmb2 и доработка к порту OpenOffice 1.1.4. 

ftp://ftp.granch.ru/pub/other/
   MAINTAINER= shelton@granch.ru
   COMMENT= SMB/CIFS shares mounting scripts to do it at login
   RUN_DEPENDS= findsmb:${PORTSDIR}/net/samba3 \
   sudo:${PORTSDIR}/security/sudo \
   gawk:${PORTSDIR}/lang/gawk
   USE_BZIP2= yes
   NO_BUILD= yes
   .include <bsd.port.pre.mk>
   do-install:
   .for i in smb2awk smb2nsmbrc mountsmb2
   ${INSTALL_SCRIPT} ${WRKSRC}/${i} ${PREFIX}/bin
   .endfor
    -@${MKDIR} ${EXAMPLESDIR}
   .for i in sudoers .login .nsmbrc .mssmbrc
   ${INSTALL_DATA} ${WRKSRC}/${i} ${EXAMPLESDIR}
   .endfor
    -@${MKDIR} ${DOCSDIR}
   ${INSTALL_DATA} ${WRKSRC}/README.FreeBSD
   ${DOCSDIR}
   @${SED} -e "s,%%EXAMPLESDIR%%,${EXAMPLESDIR},g" -i .old ${PKGMESSAGE}
   @${CAT} ${PKGMESSAGE}
   @${RM} -f ${PKGMESSAGE}
   @${MV} ${PKGMESSAGE}.old ${PKGMESSAGE}
   .include <bsd.port.post.mk>
 
   В RUN_DEPENDS перечисляются все порты, от которых зависит данный скрипт, а именно GNU AWK, sudo и Samba, из которой на самом деле нужна только программа findsmb. «USE_BZIP2=yes» указывает на то, что дистрибутив упакован программой bzip2. «NO_BUILD=yes» указывает на то, что программа не требует сборки. Если этого не указать, то система будет пытаться выполнить команду make в каталоге порта, не найдет Makefile и аварийно завершится.
   Инсталляцией порт управляет самостоятельно – в Makefile присутствует заменяющая подмишень do-install. Здесь хорошо видно, как можно организовать цикл, который установит несколько файлов, перечисленных в списке, в указанное место. После первого цикла, который устанавливает собственно скрипты идет команда создания каталога для документации – система сама не будет делать ничего, все необходимые каталоги должны быть созданы портом.
   Такая странная форма записи команды означает что:
   • если команда завершается неудачно, например, такой каталог уже существует, то make не прекращает работу (минус перед командой);
   • команда не отображается на терминале (знак @ перед командой).
 
   Потом идет второй цикл, который устанавливает файлы примеров в каталог, который для этого предварительно создается, создается каталог документации и в него копируется файл README.FreeBSD.
   Команда sed подготавливает файл pkg-message к отображению. В файле, который распространяется вместе с портом присутствует макроподстановка %%EXAMPLESDIR%%, которая, перед тем как это сообщение будет показано пользователю, заменяется на значение переменной ${EXAMPLESDIR}. Чтобы не изменять оригинальный файл pkg-message (возможно, в следующий раз установка будет проходить с другим значением ${EXAMPLESDIR}), старый файл сохраняется, измененный файл удаляется, старый файл переименовывается в оригинальное имя. Порт несложный, но он демонстрирует, как можно использовать заменяющие подмишени. При создании таких портов следует быть предельно внимательными – помните, что любой каталог, не входящий в стандартное дерево каталогов, описанное в bsd.local.mk, имеет право не существовать и должен быть предварительно создан. 

http://ootrans.i-rs.ru/out/:oorus
   .endif
   .if defined(USE_INFRA_PATCHSET)
   MASTER_SITES+= ftp://ftp.i-rs.ru/pub/openoffice/1.1.4/ru/:oorus
   .endif
 
   Эти строки были внесены сразу же после списка MASTER_SITES. Они задают сервера, откуда будут загружаться необходимые файлы и устанавливают группу, которая будет впоследствии связана с файлами дистрибутива.
 
   .if !defined(WITHOUT_MOZILLA)
   DISTFILES+= ${MOZILLA_PROJECT}:moz \
   ${MOZILLA_SOURCE}:mozsrc
   USE_GNOME+= orbit gtk12
   .endif
   .if defined(USE_RUSSIAN_GSI)
   GSI_VERSION= 2005-01-20
   GSI_DIR= rusgsi
   DISTFILES+= gsi-$(GSI_VERSION)-sorted.txt.bz2:oorus
   .endif
   .if defined(USE_INFRA_PATCHSET)
   INFRA_PATCHDIR= infrapatch
   INFRA_PATCHEXT= OOo_1.1.4_infra_patches
   DISTFILES+= ${INFRA_PATCHEXT}.tar.gz:oorus
   .endif
 
   Вот именно эта доработка позволила мне уменьшить сборку порта часа на два. Задание «WITHOUT_MOZILLA=yes» исключит из списка DISTFILES файлы исходного кода Mozilla Suite, и, следовательно, загружаться они не будут. Другие условия дополняют список DISTFILES файлами, содержащими модификации интерфейса (gsi-2005-01-20-sorted.txt.bz2), и набором патчей от «Инфра-Ресурс», задают имена каталогов, в которые они будут распаковываться и привязывают их к серверу в группу oorus.
 
   # When USE_RUSSIAN_GSI was defined, ensure, that
   # PREBUILD_TRANSEX3 and RUSSIAN_GSI were also defined
   .if defined(USE_RUSSIAN_GSI)
   .if !defined(PREBUILD_TRANSEX3)
   PREBUILD_TRANSEX3= yes
   GSI_PREBUILD= ${WRKDIR}/${GSI_DIR}/btransex
   .endif
   .if !defined(RUSSIAN_GSI)
   RUSSIAN_GSI= ${WRKDIR}/${GSI_DIR}/gsi-${GSI_VERSION}-sorted.txt
   .endif
   .endif
   # When USE_INFRA_PATCHSET was defined, ensure,
   # that INFRA_PATCHER was also defined
   .if defined(USE_INFRA_PATCHSET)
   INFRA_PATCHER= ${WRKDIR}/${INFRA_PATCHDIR}/${INFRA_PATCHEXT}/do_infrapatch
   .endif
 
    Для работы с файлом трансляции интерфейса потребуется начальная обработка его программой transex3, что и задается соответствующим параметром.
   Также устанавливается имя скрипта, который запустит эту программу. Это небольшой скрипт, который будет создан автоматически. Кроме того, задается имя распакованного файла трансляции элементов интерфейса и имя программы, которая будет использована для наложения патчей.
   Переходим к реальным действиям:
 
   .if defined(USE_RUSSIAN_GSI)
   @${ECHO_MSG} "===> Extracting russian GSI file"
   @${MKDIR} ${WRKDIR}/${GSI_DIR}
   @${CP} ${DISTDIR}/${DIST_SUBDIR}/gsi-${GSI_VERSION}-sorted.txt.bz2 ${WRKDIR}/${GSI_DIR}
   @cd ${WRKDIR}/${GSI_DIR} && \
   ${BZIP2_CMD} -d gsi-${GSI_VERSION}-sorted.txt.bz2
   .endif
   .if defined(USE_INFRA_PATCHSET)
   @${ECHO_MSG} "===> Extracting Infra patches set"
   @${MKDIR} ${WRKDIR}/${INFRA_PATCHDIR}
   @${CP} ${DISTDIR}/${DIST_SUBDIR}/${INFRA_PATCHEXT}.tar.gz ${WRKDIR}/${INFRA_PATCHDIR}
   @cd ${WRKDIR}/${INFRA_PATCHDIR} && \
   ${TAR} -xzvf ${INFRA_PATCHEXT}.tar.gz
   .endif
 
   Копируем упакованный файл трансляции интерфейса из /usr/ports/distfiles/openoffice (задана DIST_SUBDIR) в каталог, который был создан заранее, и распаковываем его архиватором bzip2. Копируем архив патчей «Инфра-Ресурс» в другой, предварительно созданный каталог и распаковываем его, но уже программой tar. Обратите внимание, что все команды параметризированы, – всюду используется ${PROGRAM}, а не /bin/program!
 
   post-patch:
   .if defined(USE_INFRA_PATCHSET)
   @${ECHO_MSG} "===> Patching OOo with Infra patches set"
   @cd ${WRKDIR}/${INFRA_PATCHDIR}/${INFRA_PATCHEXT} && \
   ${SH} ${INFRA_PATCHER}
   .endif
 
   Дополняем мишень patch подмишенью post-patch, в которой собственно и запускаем скрипт, вносящий изменения. Обратите внимание – записать это в две строки нельзя! Если записать команды cd и запуск скрипта на разных строках, то запуск скрипта произойдет не из каталога, в который перешли командой cd, а из текущего, потому что make, выполнив запрошенное действие, возвращается в каталог, из которого она была запущена. Точно так же выполняются все другие действия, связанные со сменой каталога, – например распаковка файлов.
 
   .if defined(PREBUILD_TRANSEX3)
   @${ECHO_MSG} "===> Pre-build TRANSEX3"
   @${ECHO} "source ${WRKSRC}/FreeBSDEnv.Set"
   > ${GSI_PREBUILD}
   @${ECHO} "cd transex3 && build --all && deliver"
   >> ${GSI_PREBUILD}
   @${CHMOD} +x ${GSI_PREBUILD}
   @cd ${WRKSRC} && PATH="${PATH}:${LOCALBASE}/bin:${LOCALBASE}/sbin" && ${TCSH} ${GSI_PREBUILD}
   .endif
   .if defined(USE_RUSSIAN_GSI)
   @${ECHO_MSG} "===> Build russian GSI"
   @cd ${WRKSRC} && PATH="${PATH}:${LOCALBASE}/bin:${LOCALBASE}/sbin" && ${TCSH} -c 'source FreeBSDEnv.Set && localize -m -i ru-RU -l ${LANG_EXT} -f ${RUSSIAN_GSI}'
   .endif
 
   Первая часть задает предварительную сборку программы transex3, для чего формируется скрипт, затем осуществляется переход в каталог с распакованными исходниками и запуск сборки. Обратите внимание, как передается значение переменной PATH. Вторая часть задает обработку исходных текстов OpenOffice согласно новому файлу локализации интерфейса.
   Полный текст Makefile из editors/openoffice-1.1 с внесенными мной изменениями можно скачать с [3]. Этот файл уже не используется как файл порта, но как образец написания Makefile, там есть чему поучиться. 

Некоторые переменные USE_*

   Здесь описаны некоторые наиболее часто используемые переменные USE_*, не упомянутые до сих пор. Полный список их значительно больше, смотреть его нужно в bsd.port.mk.
   • IGNOREFILES= <список файлов>– задает список файлов, для которых не выполняется проверка контрольной суммы из distinfo.
   • EXTRACT_ONLY=yes– только распаковать файлы дистрибутива, не выполнять никакой работы по сборке. Как правило, в таком порту применяется заменяющая подмишень do-install.
   • RESTRICTED=yes– запрещает помещать собранный пакет на FTP или распространять на CD-ROM. Как правило вследствие лицензионных ограничений. Это не такая уже редкость, например такое ограничение имеет виртуальная машина Java.
   • NO_CDROM=yes– почти то же самое, только разрешает помещение на FTP.
   • FORBIDDEN=yes– запрещает сборку из-за уязвимостей программы.
   • IGNORE=yes– запрещает сборку из-за грубых ошибок при сборке программы. Фактически используется для прекращения работы системы по каким-либо причинам (например, неподдерживаемая версия FreeBSD).
   • BROKEN=yes– запрещает сборку из-за различных ошибок.
   • USE_ZIP=yes– для распаковки использовать zip.
   • USE_DOS2UNIX=yes– все тексты перекодировать таким образом, чтобы преобразовать переводы строк из вида DOS в вид UNIX.
   • USE_GCC=<номер>– задает номер версии компилятора GCC. Я помню только один порт, использовавший эту USE_* – editors/openoffice на 4.х, имевший по умолчанию GCC 2.95.4.
   • USE_GETOPT_LONG=yes– для 4.х добавляет зависимость от libgnugetopt. Для 5.х и выше уже неактуально – libgnugeopt перенесена в базовую систему.
   • USE_PERL=yes, USE_JAVA=yes, USE_PYTHON=yes,
    • USE_RUBY=yes– добавляют соответствующие зависимости от интерпретатора соответствующего языка.
   • USE_AUTOTOOLS=<tool>:<version>– добавляет зависимость от некоторой программы из GNU Autotools. Если задана и программа и версия, задает зависимость от конкретной версии, если версия опущена, то задает зависимость от программы без номера в имени. Например: «USE_AUTOTOOLS=libtool:15» задает зависимость от devel/libtool15, но «USE_AUTOTOOLS=libtool» задает зависимость от devel/libtool, что может быть совсем не одно и то же!
   • USE_GNOME=<список компонентов через пробел>– задает зависимости от перечисленного списка компонентов GNOME. Например, приведенная выше строка: «USE_GNOME+= orbit gtk12» задает зависимости от компонентов devel/orbit и x11-toolkits/gtk12. При задании зависимостей следует придерживаться разумного минимума – указывать только те компоненты, которые действительно нужны для работы. Помните, что подключенные компоненты тоже имеют свои зависимости, которые могут иметь свои зависимости и т. д. – глубина вложенности неограничена.
   • USE_QT_VER=3– добавляет зависимость от библиотеки x11-toolkits/qt33 и неявно подключает файл bsd.kde.mk.
   • USE_LINUX={yes|<число>}– добавляет зависимость от порта emulators/linux-base-8, если не указано <число>. Если <число> указано, то добавляется зависимость от порта emulators/linux-base-<число>.
   • CONFLICTS=<список портов>– содержит список портов, с которыми может конфликтовать данный порт. Конфликт может выражаться в совпадающих именах каталогов для установки, совпадающих именах файлов, одинаковых TCP/UDP-портах, невозможность сборки одного порта при наличии другого и прочих причинах. Выражение для списка портов может содержать мета-символы «*?[]!». Например, «apache*-1.3.[012345]».

Заключение

   Наша работа закончена, но жизнь продолжается... Мы рассмотрели основные возможности системы сборки портов. Однако далеко не для каждого порта требуется такое количество работы – для многих несложных программ порт от начала до конца, включая отсылку во FreeBSD Team, пишется за полдня. Система сборки портов обладает очень большими возможностями. Изучать их все нет необходимости – всегда можно заглянуть в bsd.port.mk, который и является главным справочником по ее возможностям.
   В начале файла идет громадный блок комментария, в котором перечислены все переменные, которые можно использовать, и даны к ним краткие описания, для чего они предназначены. Число программ, которые работают под FreeBSD, постоянно увеличивается, порты для них пишутся, как мы теперь видим, обычными людьми, и, создавая новый порт для программы, которая там в данный момент отсутствует, мы не только облегчаем себе жизнь, но и помогаем сообществу.