--- description: 'Список распространённых рекомендаций и ошибок, встречающихся в процессе портирования на FreeBSD' next: books/porters-handbook/porting-samplem params: path: /books/porters-handbook/porting-dads/ prev: books/porters-handbook/security showBookMenu: 'true' tags: ["dos", "don'ts", "porting", "ports", "guide"] title: 'Глава 13. Что делать нужно, и что делать нельзя' weight: 13 --- [[porting-dads]] = Что делать нужно, и что делать нельзя :doctype: book :toc: macro :toclevels: 1 :icons: font :sectnums: :sectnumlevels: 6 :sectnumoffset: 13 :partnums: :source-highlighter: rouge :experimental: :freebsd-version: __FreeBSD_version :freebsd: __FreeBSD__ :images-path: books/porters-handbook/ ifdef::env-beastie[] ifdef::backend-html5[] :imagesdir: ../../../../images/{images-path} endif::[] ifndef::book[] include::shared/authors.adoc[] include::shared/mirrors.adoc[] include::shared/releases.adoc[] include::shared/attributes/attributes-{{% lang %}}.adoc[] include::shared/{{% lang %}}/teams.adoc[] include::shared/{{% lang %}}/mailing-lists.adoc[] include::shared/{{% lang %}}/urls.adoc[] toc::[] endif::[] ifdef::backend-pdf,backend-epub3[] include::../../../../../shared/asciidoctor.adoc[] endif::[] endif::[] ifndef::env-beastie[] toc::[] include::../../../../../shared/asciidoctor.adoc[] endif::[] [[dads-intro]] == Введение Вот список часто встречающихся действий, которые нужно и которые нельзя делать во время процесса портирования. Проверьте порт по этому списку, и также проверьте порты в https://bugs.FreeBSD.org/search/[базе сообщений PR], которые присланы другими людьми. Присылайте любые комментарии о портах, которые вы проверили, так, как это описано в статье о extref:{contributing}[Сообщениях об ошибках и общих замечаниях, CONTRIB-GENERAL]. Проверка портов в базе сообщений PR позволит нам быстрее коммитить их и удостовериться, что вы знаете, что делаете. [[porting-wrkdir]] == `WRKDIR` Не пишите ничего в файлы вне каталога `WRKDIR`. Каталог `WRKDIR` является единственным местом, которое гарантированно будет доступно для записи во время построения порта (обратитесь к главе об extref:{handbook}[установке портов с CDROM, PORTS-CD] за примером построения портов из дерева, доступного только для чтения). Если вам нужно изменить какой-либо из файлов [.filename]##pkg-*##, сделайте это, crossref:pkg-files[pkg-names,переопределив переменную], но не перезаписывая их. [[porting-wrkdirprefix]] == `WRKDIRPREFIX` Добейтесь того, чтобы ваш порт принимал во внимание значение переменной `WRKDIRPREFIX`. Большинство портов об этом не заботятся. В частности, если вы обращаетесь к каталогу `WRKDIR` другого порта, заметьте, что его правильным местоположением является [.filename]#WRKDIRPREFIXPORTSDIR/subdir/name/work#, а не [.filename]#PORTSDIR/subdir/work# или [.filename]#.CURDIR/../../subdir/name/work# или что-то подобное. Кроме того, если вы сами задаете `WRKDIR`, то должны поставить перед ним знак `${WRKDIRPREFIX}${.CURDIR}`. [[porting-versions]] == Различение операционных систем и версий ОС Вы можете встретиться с кодом, который требует модификаций или условной компиляции в зависимости от того, с какой версией FreeBSD Unix он работает. Предпочтительным способом отделения кода для версий FreeBSD является использование макросов {freebsd-version} и {freebsd}, определённых в https://cgit.freebsd.org/src/tree/sys/sys/param.h[sys/param.h]. Если этот файл не подключен, добавьте код [.programlisting] .... #include .... в нужном месте файла [.filename]#.c#. {freebsd} определён во всех версиях FreeBSD в качестве старшего номера версии системы. Например, в FreeBSD 9.x {freebsd} определён со значением `9`. [.programlisting] .... #if __FreeBSD__ >= 9 # if __FreeBSD_version >= 901000 /* 9.1+ release specific code here */ # endif #endif .... Полный список значений `{freebsd-version}` доступен в crossref:versions[versions,Значения __FreeBSD_version]. [[dads-after-port-mk]] == Написание чего-либо после bsd.port.mk Не пишите ничего после строки `.include `. Этой строки можно избежать, включив в где-то в середину вашего файла [.filename]#Makefile# файл [.filename]#bsd.port.pre.mk#, и файл [.filename]#bsd.port.post.mk# в конец. [IMPORTANT] ==== Вам нужно включить либо пару файлов [.filename]#bsd.port.pre.mk#/[.filename]#bsd.port.post.mk#, либо только [.filename]#bsd.port.mk#; не используйте оба этих метода одновременно. ==== В файле [.filename]#bsd.port.pre.mk# определяются лишь несколько переменных, которые могут быть использованы в тестах из файла [.filename]#Makefile#, в файле [.filename]#bsd.port.post.mk# заданы остальные. Вот некоторые важные переменные, определённые в файле [.filename]#bsd.port.pre.mk# (это не полный список, для выяснения полного списка прочтите, пожалуйста, сам файл [.filename]#bsd.port.mk#). [.informaltable] [cols="1,1", frame="none", options="header"] |=== | Переменная | Описание |`ARCH` |Архитектура машины в виде, получаемом по команде `uname -p` (например, `i386`) |`OPSYS` |Тип операционной системы, получаемый по команде `uname -s` (например, `FreeBSD`) |`OSREL` |Версия релиза операционной системы (например, `2.1.5` или `2.2.7`) |`OSVERSION` |Версия операционной системы в виде числа, та же, что и crossref:versions[versions,`{freebsd-version}`]. |`LOCALBASE` |Корень дерева "local" (например, `/usr/local`) |`PREFIX` |Куда, собственно, устанавливается порт (обратитесь к crossref:testing[porting-prefix,подробной информации о `PREFIX`]). |=== [NOTE] ==== Если вы задаете переменную `MASTERDIR`, делайте это до подключения [.filename]#bsd.port.pre.mk#. ==== Вот несколько примеров того, что вы можете написать после [.filename]#bsd.port.pre.mk#: [.programlisting] .... # no need to compile lang/perl5 if perl5 is already in system .if ${OSVERSION} > 300003 BROKEN= perl is in system .endif .... Вы не забываете об использовании табуляции вместо пробелов после `BROKEN=`. [[dads-sh-exec]] == Использование выражения `exec` в сценариях обёртках Если порт устанавливает сценарий на языке shell, который служит для запуска другой программы, и если запуск этой программы является последним действием сценария, убедитесь, что запуск программы производится с использованием выражения `exec`, например: [.programlisting] .... #!/bin/sh exec %%LOCALBASE%%/bin/java -jar %%DATADIR%%/foo.jar "$@" .... Выражение `exec` заменяет процесс сценария на указанную программу. Если `exec` опущен, то процесс сценария во время работы программы остаётся в памяти, бесполезно потребляя системные ресурсы. [[dads-rational]] == Поступайте разумно Файл [.filename]#Makefile# должен выполнять действия просто и небеспричинно. Если вы можете сделать что-то на несколько строк короче или более читабельно, сделайте это. В качестве примеров можно привести использование конструкций `.if` утилиты make вместо соответствующей конструкции `if` командного процессора, ненужность переопределения цели `do-extract` при возможности переопределения `EXTRACT*` и использование `GNU_CONFIGURE` вместо `CONFIGURE_ARGS += --prefix=${PREFIX}`. Если вы обнаружите, что для выполнения чего-то приходится писать много нового кода, то, пожалуйста, просмотрите файл [.filename]#bsd.port.mk# на предмет того, не содержит ли он решение именно вашей проблемы. Хотя его трудно читать, имеется много проблем, выглядящих сложными, для которых файл [.filename]#bsd.port.mk# уже содержит быстрое решение. [[dads-cc]] == Относитесь внимательно как к `CC`, так и `CXX` Порт должен принимать во внимание как переменную `CC`, так и `CXX`. Под этим мы подразумеваем, что порт ни в коем случае не должен устанавливать значения этих переменных, переопределяя имеющиеся значения; вместо этого можно добавлять нужные значения к уже имеющимся. Это связано с тем, что параметры построения, относящиеся ко всем портам, могут быть заданы глобально. Если порт не учитывает значения этих переменных, добавьте строку `NO_PACKAGE=ignores either cc or cxx` в файл [.filename]#Makefile#. Далее следует пример файла [.filename]#Makefile#, использующего как переменную `CC`, так и `CXX`. Обратите внимание на использование символов `?=`: [.programlisting] .... CC?= gcc .... [.programlisting] .... CXX?= g++ .... Вот пример, в котором не принимаются во внимание ни `CC`, ни `CXX`: [.programlisting] .... CC= gcc .... [.programlisting] .... CXX= g++ .... В системах FreeBSD обе переменные `CC` и `CXX` могут быть определены в файле [.filename]#/etc/make.conf#. В первом примере задаётся значение, если оно ранее не было определено в [.filename]#/etc/make.conf#, что сохраняет любые определения, данные на уровне системы в целом. Второй пример переопределяет всё, что было задано ранее. [[dads-cflags]] == Относитесь внимательно к `CFLAGS` Порт должен учитывать переменную `CFLAGS`. Под этим мы подразумеваем, что порт ни в коем случае не должен устанавливать значения этой переменной, переопределяя имеющиеся значения; вместо этого можно добавлять нужные значения к уже имеющимся. Это связано с тем, что параметры построения, относящиеся ко всем портам, могут быть заданы глобально. Если порт не учитывает значения этой переменной, добавьте строку `NO_PACKAGE=ignores cflags` в файл [.filename]#Makefile#. Далее следует пример файла [.filename]#Makefile#, использующего переменную `CFLAGS`. Обратите внимание на использование символов `+=`: [.programlisting] .... CFLAGS+= -Wall -Werror .... А вот пример, в котором не учитывается значение переменной `CFLAGS`: [.programlisting] .... CFLAGS= -Wall -Werror .... В системе FreeBSD переменная `CFLAGS` определена в файле [.filename]#/etc/make.conf#. В первом примере к переменной `CFLAGS` добавляются дополнительные флаги, при этом сохраняются все определения, данные ранее на уровне системы. Во втором примере всё, что было задано ранее, игнорируется. Из сторонних файлов [.filename]#Makefile# следует удалить флаги оптимизации. Общесистемные флаги оптимизации находятся в системной переменной `CFLAGS`. Пример из немодифицированного [.filename]#Makefile#: [.programlisting] .... CFLAGS= -O3 -funroll-loops -DHAVE_SOUND .... При использовании системных флагов оптимизации [.filename]#Makefile# станет похожим на следующий пример: [.programlisting] .... CFLAGS+= -DHAVE_SOUND .... [[dads-verbose-logs]] == Подробные журналы сборки Заставьте систему сборки портов отображать все команды, выполняемые на этапе сборки. Полные журналы сборки критически важны для отладки проблем с портами. Пример неинформативного журнала сборки (плохой): [.programlisting] .... CC source1.o CC source2.o CCLD someprogram .... Пример подробного журнала сборки (хороший): [.programlisting] .... cc -O2 -pipe -I/usr/local/include -c -o source1.o source1.c cc -O2 -pipe -I/usr/local/include -c -o source2.o source2.c cc -o someprogram source1.o source2.o -L/usr/local/lib -lsomelib .... Некоторые системы сборки, такие как CMake, ninja и GNU configure, настроены на подробное ведение журнала в рамках инфраструктуры портов. В других случаях портам могут потребоваться индивидуальные изменения. [[dads-feedback]] == Обратная связь Посылайте подходящие изменения/патчи автору/сопровождающему для включения в следующий релиз. Это только сделает вашу работу гораздо легче при выходе следующего релиза. [[dads-readme]] == README.html [.filename]#README.html# не является частью порта и генерируется при помощи `make readme`. Не включайте этот файл в патчи или коммиты. [NOTE] ==== Если не удается выполнить `make readme`, убедитесь, что значение по умолчанию `ECHO_MSG` не изменено внутри порта. ==== [[dads-noinstall]] == Пометка неустанавливаемого порта как `BROKEN`, `FORBIDDEN` или `IGNORE` В некоторых случаях пользователи не должны допускаться к установке порта. Для того, чтобы сообщить пользователю, что порт не следует устанавливать, имеется несколько `make`-переменных, которые могут быть использованы в файле [.filename]#Makefile# порта. Значения следующих `make`-переменных будут причиной, возвращаемой пользователям, по которой порт отказывает в установке. Пожалуйста, используйте корректные `make`-переменные, так как каждая переменная make передаёт абсолютно различный смысл как для пользователей, так и для автоматизированных систем, которые полагаются на файлы [.filename]#Makefile#, таких как crossref:keeping-up[build-cluster,кластер построения портов], crossref:keeping-up[freshports,FreshPorts]. [[dads-noinstall-variables]] === Переменные * `BROKEN` предназначена для портов, которые в настоящее время не компилируются, не устанавливаются или не удаляются правильно. Следует использовать, когда проблема считается временной. + В особых случаях кластер построения будет продолжать попытки собрать их, чтобы показать, решена ли основная проблема. (Однако, как правило, кластер запускается без этой возможности.) + В частности, используйте `BROKEN`, когда порт: ** не компилируется ** выполняет со сбоем конфигурирование или процесс установки ** устанавливает файлы вовне [.filename]#${PREFIX}# ** не удаляет полностью все свои файлы при деинсталляции (тем не менее, это может быть допустимо, и подходит для портов, оставляющих после себя файлы, измененные пользователем) ** имеет проблемы во время выполнения на системах, где он должен работать нормально. * `FORBIDDEN` используется для портов, которые содержат уязвимости в информационной безопасности или являются потенциально вредными в плане обеспечения информационной безопасности системы FreeBSD при установке данного порта (например: заведомо небезопасная программа или программа, которая предоставляет легко взламываемые сервисы). Порты должны помечаться как `FORBIDDEN`, как только в конкретном программном обеспечении обнаружилась уязвимость, но обновление выпущено не было. В идеальном случае порты должны обновляться максимально быстро после обнаружения уязвимости, чтобы уменьшить число уязвимых хостов FreeBSD (нам нравится иметь репутацию безопасной системы), однако иногда случается значительный временной разрыв между обнаружением уязвимости и выходом обновлённого релиза уязвимого программного обеспечения. Не помечайте порт как `FORBIDDEN`, если причина не вызвана соображениями информационной безопасности. * `IGNORE` предназначена для портов, которые не должны строиться по какой-либо другой причине. Следует использовать для портов, в случае когда проблема считается структурной. Кластер построения ни при каких условиях не будет строить порты, помеченные как `IGNORE`. В частности, используйте `IGNORE`, когда порт: ** не работает на установленной версии FreeBSD ** имеет distfile, который не может быть автоматически загружен из-за ограничений лицензирования ** не работает с некоторыми другими установленными портами (например, порт зависит от package:www/drupal7[], но установлен package:www/drupal8[]) + [NOTE] ==== Если порт будет конфликтовать с уже установленным портом (например, если они устанавливают файл в то же место, но с иным функциональным назначением), то crossref:makefiles[conflicts,используйте вместо этого `CONFLICTS`]. `CONFLICTS` сам установит значение `IGNORE`. ==== [[dads-noinstall-notes]] === Заметки о реализации Не заключайте значения переменных `BROKEN`, `IGNORE` и связанных с ними в кавычки. Из-за способа отображения информации пользователю, формулировка сообщений для каждой переменной отличается: [.programlisting] .... BROKEN= fails to link with base -lcrypto .... [.programlisting] .... IGNORE= unsupported on recent versions .... и в результате `make describe` выведен информацию в таком виде : [.programlisting] .... ===> foobar-0.1 is marked as broken: fails to link with base -lcrypto. .... [.programlisting] .... ===> foobar-0.1 is unsupported on recent versions. .... [[dads-arch]] == Архитектурные соображения [[dads-arch-general]] === Общие замечания об архитектурах FreeBSD работает на гораздо большем количестве архитектур процессоров, чем только хорошо известные x86-совместимые. Некоторые порты имеют ограничения, характерные для одной или нескольких из этих архитектур. Для списка поддерживаемых архитектур выполните: [.programlisting] .... cd ${SRCDIR}; make targets .... Значения отображаются в форме `TARGET`/`TARGET_ARCH`. Переменная только для чтения `ARCH` в ports устанавливается на основе значения `TARGET_ARCH`. [.filename]##Makefile## в портах должны проверять значение этой переменной. [[dads-arch-neutral]] === Пометка порта как архитектурно нейтрального Порты, которые не имеют зависимых от архитектуры файлов или требований, определяются установкой `NO_ARCH=yes`. Пакеты, собранные из таких портов, имеют строку архитектуры, оканчивающуюся на `:*` (архитектура с подстановочным символом), в отличие от, например, `freebsd:13:x86:64` (архитектура amd64). [NOTE] ==== `NO_ARCH` предназначен для указания того, что нет необходимости собирать пакет для каждой из поддерживаемых архитектур. Цель состоит в том, чтобы сократить количество ресурсов, затрачиваемых на сборку и распространение пакетов, таких как сетевой трафик и дисковое пространство на зеркалах и на носителях дистрибутива. Однако в настоящее время наша инфраструктура пакетов (например, менеджеры пакетов, зеркала и сборщики пакетов) не настроена для полного использования преимуществ `NO_ARCH`. ==== [[dads-arch-ignore]] === Пометка порта как игнорируемого только на определённых архитектурах * Чтобы пометить порт как ``IGNORE`` только для определённых архитектур, существуют две другие удобные переменные, которые автоматически устанавливают `IGNORE`: `ONLY_FOR_ARCHS` и `NOT_FOR_ARCHS`. Примеры: + [.programlisting] .... ONLY_FOR_ARCHS= i386 amd64 .... + [.programlisting] .... NOT_FOR_ARCHS= ia64 sparc64 .... + Пользовательское сообщение `IGNORE` можно задать с помощью `ONLY_FOR_ARCHS_REASON` и `NOT_FOR_ARCHS_REASON`. Для отдельных архитектур возможны записи с `ONLY_FOR_ARCHS_REASON_ARCH` и `NOT_FOR_ARCHS_REASON_ARCH`. [[dads-arch-i386]] * Если порт загружает и устанавливает бинарные файлы i386, установите `IA32_BINARY_PORT`. Если эта переменная задана, [.filename]#/usr/lib32# должен присутствовать для IA32-версий библиотек, а ядро должно поддерживать совместимость с IA32. Если одно из этих двух условий не выполняется, `IGNORE` будет установлен автоматически. [[dads-arch-cluster]] === Специфические аспекты для кластеров * Некоторые порты пытаются оптимизировать себя под конкретную машину, на которой они собираются, указывая компилятору `-march=native`. Этого следует избегать: либо добавить этот параметр в опцию, отключенную по умолчанию, либо удалить его полностью. + В противном случае стандартный пакет, созданный кластером сборки, может не запускаться на каждой машине с данной `ARCH`. [[dads-deprecated]] == Пометка порта на удаление с `DEPRECATED` или `EXPIRATION_DATE` Помните, что `BROKEN` и `FORBIDDEN` будут использованы как временное средство, если порт не является работающим. Постоянно неработоспособные порты должны полностью удаляться из дерева. В подходящих ситуациях пользователи могут быть оповещены о предстоящем удалении через переменные `DEPRECATED` и `EXPIRATION_DATE`. Первое - это просто строка, сообщающая причину запланированного удаления порта; вторая является строкой в формате ISO 8601 (YYYY-MM-DD). Обе будут показаны пользователю. Переменную `DEPRECATED` можно установить без использования `EXPIRATION_DATE` (в частности, при рекомендации новой версии порта), но обратный порядок не имеет никакого смысла. [NOTE] ==== При пометке порта как `DEPRECATED`, если существуют альтернативные порты, которые можно использовать вместо устаревающего, удобно упомянуть их в сообщении коммита. ==== Не существует установленного правила о том, насколько заранее нужно уведомлять. Текущая практика предполагает один месяц для проблем, связанных с безопасностью, и два месяца для проблем сборки. Это также даёт заинтересованным коммиттерам немного времени на исправление проблем. [[dads-dot-error]] == Избегайте использования конструкции `.error` Правильным способом подать сигнал для [.filename]#Makefile# о том, что порт не может быть установлен из-за какого-то внешнего фактора (например, пользователь указал недопустимую комбинацию опций построения), является установка непустого значения для `IGNORE`. Это значение будет сформатировано и показано пользователю во время `make install`. Использование для этих целей `.error` является распространённой ошибкой. Проблема в том, что в этой ситуации будут повреждены многие инструменты автоматизации, работающие с деревом портов. Наибольшим образом это распространено при попытке построить [.filename]#/usr/ports/INDEX# (смотрите crossref:testing[make-describe, Запуск `make describe`]). Тем не менее, даже более простые команды, такие как `make maintainer`, в этом случае также вернут ошибку. Это не является приемлемым. [[dot-error-breaks-index]] .Как избегать использования `.error` [example] ==== Из следующих двух вариантов строки файла [.filename]#Makefile# первый приведёт к неудачному завершению работы `make index`, а второй - нет: [.programlisting] .... .error "option is not supported" .... [.programlisting] .... IGNORE=option is not supported .... ==== [[dads-sysctl]] == Использование sysctl Использование [.filename]#sysctl# не рекомендуется, кроме как при выполнении целей. Это вызвано тем, что вычисление любых `makevar`, таких как во время команды `make index`, с необходимостью запуска этой команды, ещё больше замедляет весь процесс. man:sysctl[8] следует всегда использовать через переменную `SYSCTL`, поскольку она содержит полностью заданный путь, и при необходимости может быть переопределена. [[dads-rerolling-distfiles]] == Меняющиеся дистрибутивные файлы Иногда авторы программного обеспечения изменяют содержимое выпущенных дистрибутивных файлов, не меняя их названия. Убедитесь, что изменения официальны и были выполнены автором. В прошлом случалось, что дистрибутивный файл тихо изменялся на серверах загрузки с целью нанесения вреда или компрометации безопасности конечного пользователя. Отложите старый distfile в сторону, загрузите новый, распакуйте их и сравните содержимое с помощью man:diff[1]. Если ничего подозрительного нет, обновите [.filename]#distinfo#. [IMPORTANT] ==== Убедитесь, что вы выделили основные различия в PR и журнале коммитов, чтобы другие люди знали, что ничего плохого не произошло. ==== Свяжитесь с автором этого программного обеспечения для подтверждения изменений. [[dads-use-posix-standards]] == Используйте стандарты POSIX В большинстве случаев порты FreeBSD ожидают соответствия стандарту POSIX. Некоторые программы и системы сборки делают предположения, основанные на конкретной операционной системе или окружении, что может вызывать проблемы при использовании в порте. Не используйте [.filename]#/proc#, если есть другие способы получить информацию. Например, `setprogname(argv[0])` в `main()`, а затем man:getprogname[3] для получения имени исполняемого файла. Не полагайтесь на поведение, не документированное в POSIX. Не записывайте метки времени в критическом пути приложения, если оно работает и без них. Получение меток времени может быть медленным в зависимости от точности меток времени в ОС. Если метки времени действительно необходимы, определите, насколько точными они должны быть, и используйте API, которое, согласно документации, предоставляет только необходимую точность. Ряд простых системных вызовов (например, man:gettimeofday[2], man:getpid[2]) работают намного быстрее в Linux(R) по сравнению с любой другой операционной системой из-за кэширования и используемой оптимизации vsyscall. Не полагайтесь на их дешевизну в критичных к производительности приложениях. В целом, старайтесь избегать системных вызовов там, где это возможно. Не полагайтесь на специфичное для Linux(R) поведение сокета. В частности, отличаются размеры буфера сокета по умолчанию (выполните вызов man:setsockopt[2] с `SO_SNDBUF` и `SO_RCVBUF`, и в то время как в Linux(R) при заполнении буфера сокета man:send[2] блокируется, FreeBSD возвращает ошибку и устанавливает `ENOBUFS` в качестве значения errno. Если требуется рассчитывать на нестандартное поведение, инкапсулируйте это должным образом в общий для всех API с проверкой поведения на этапе конфигурации, и если требуемое поведение не найдено, прекращайте выполнение. Используйте https://www.freebsd.org/cgi/man.cgi[страницы справочника] для проверки, относится ли функция к интерфейсу POSIX (ищите раздел "STANDARDS" на странице справочника). Не рассчитывайте на то, что в качестве [.filename]#/bin/sh# используется bash. Убедитесь, что командная строка, переданная в man:system[3], будет работать в POSIX-совместимой оболочке. Список основных bash-измов расположен https://wiki.ubuntu.com/DashAsBinSh[здесь]. Проверьте, что используемые заголовочные файлы включены в POSIX или список, рекомендуемый страницей справочника, т.к. например, забыть подключить [.filename]#sys/types.h# - не такая уж проблема в Linux(R), однако это не так во FreeBSD. [[dads-misc]] == Разное Файлы [.filename]#pkg-descr# и [.filename]#pkg-plist# должны проверяться дважды. Если вы пересматриваете порт и думаете, что его можно описать иначе, сделайте это. Будьте внимательны с юридическими вопросами! Не делайте из нас нелегальных распространителей ПО!