% cp file file.orig
Глава 4. Медленное портирование
Этот перевод может быть устаревшим. Для того, чтобы помочь с переводом, пожалуйста, обратитесь к Сервер переводов FreeBSD.
Содержание
Итак, все оказалось не так уж и просто, и порт потребовал некоторых модификаций для того, чтобы заставить его работать. В этом разделе мы расскажем, шаг за шагом, как его модифицировать, чтобы он работал с нашей системой портов.
4.1. Как всё это работает
Во-первых, когда пользователь дает в своем каталоге с портом команду make
, происходит целая череда событий. Во время чтения этого текста может оказаться полезным иметь файл bsd.port.mk открытым в другом окне, что сильно поможет его понять.
Но не волнуйтесь сильно, если вы не до конца понимаете, что делается в bsd.port.mk, не так уж много людей его понимает… :-)
Запускается цель
fetch
. Цельfetch
отвечает за то, что архив исходных текстов имеется в наличии локально в каталогеDISTDIR
. Если цельfetch
не может найти требуемые файлы в каталогеDISTDIR
, то они будут искаться по указателю URLMASTER_SITES
, который устанавливается в Makefile, а также на наших FTP зеркалах, куда мы по возможности помещаем дистрибутивные файлы для архива. Затем она попытается сгрузить указанный файл с помощьюFETCH
, полагая, что запрашивающая машина имеет прямое подключение к Интернет. Если файл скачается удачно, то он будет помещен в каталогDISTDIR
для последующего использования и обработки.Выполняется цель
extract
. Она ищет дистрибутивный файл порта (как правило, tar-архивgzip
) в каталогеDISTDIR
и распаковывает его во временный каталог, задаваемый переменнойWRKDIR
(по умолчанию work).Выполняется цель
patch
. Во-первых, применяются все патчи, заданные переменнойPATCHFILES
. Во-вторых, если какие-либо файлы с патчами, носящие имена patch-*, имеются в подкаталогеPATCHDIR
(по умолчанию это каталог files), то они применяются в этот момент в алфавитном порядке.Запускается цель
configure
. Здесь может выполняться любая из многих различных вещей.Если он существует, запускается scripts/configure.
Если установлены
HAS_CONFIGURE
илиGNU_CONFIGURE
, запускается WRKSRC/configure.
Выполняется цель
build
. Она отвечает за переход в собственный рабочий каталог порта (WRKSRC
) и его построение.Выполняется цель
stage
. Конечный набор построенных файлов помещается во временный каталог (STAGEDIR
, смотрите Staging). Иерархия этого каталога отражает иерархию каталогов системы, в которую данный пакет будет устанавливаться.Выполняется цель
package
. При этом создается пакет с использованием файлов из временного каталога, созданного во время выполнения целиstage
, и файла pkg-plist порта.Выполняется цель
install
. Это устанавливает пакет, созданный во время целиpackage
, в хост-систему.
Выше перечислены стандартные действия. Кроме того, вы сами можете определить цели pre-что-то
или post-что-то
, или создать скрипты с такими именами в подкаталоге scripts, и они будут запущены до или после выполнения действий по умолчанию.
Например, если у вас есть цель post-extract
, определённая в вашем файле Makefile и файл pre-build в подкаталоге scripts, то после выполнения обычных действий по распаковке, будет вызвана цель post-extract
а скрипт pre-build будет выполнен перед запуском стандартных правил построения. Рекомендуется использовать цели из Makefile, если действия достаточно просты, потому что в дальнейшем будет проще определить, какие нестандартные действия требует порт.
Действия по умолчанию выполняются целями do-что-то
из bsd.port.mk. Например, команды для распаковки порта находятся в цели do-extract
. Если вам не хватает цели по умолчанию, вы можете ее исправить, переопределив цель do-something
в вашем файле Makefile.
"Основные" цели (к примеру, |
Теперь, когда вы представляете, что происходит, когда пользователь набирает команду make install
, давайте пройдемся через шаги, рекомендуемые для создания настоящего порта.
4.2. Получение исходного кода
Получите оригинальные исходные тексты (обычно) в виде упакованного tar-архива (foo.tar.gz или foo.tar.bz2) и скопируйте его в каталог DISTDIR
. Всегда используйте исходные тексты основной ветки разработки везде, где это возможно.
Вам потребуется задать значение переменной MASTER_SITES
так, чтобы оно указывало на местоположение оригинального tar-архива. В файле bsd.sites.mk вы найдёте краткие обозначения для большинства популярных сайтов. Пожалуйста, используйте эти сайты-и соответствующие определения-везде, где это возможно, чтобы избежать проблем повторения одной и той же информации в базе источников. Так как эти сайты со временем меняются, для всех причастных поддержка становится настоящим кошмаром. Для подробностей смотрите MASTER_SITES
.
Если вы не можете найти FTP/HTTP сайт с хорошим подключением к сети, или находите только сайты, которые имеют раздражающе нестандартные форматы, то можете захотеть поместить копию на надежный сервер FTP или HTTP, который вам доступен (например, ваша домашняя страница).
Если вы не можете найти доступного и надёжного места для помещения дистрибутивного файла, то мы сами сможем разместить его на сервере ftp.FreeBSD.org
; однако это наименее рекомендуемое решение. Дистрибутивный файл должен быть помещён в каталог ~/public_distfiles/ одного из пользователей машины freefall
. Попросите того, кто коммиттил ваш порт, сделать это. Этот человек также задаст переменной MASTER_SITES
значение MASTER_SITE_LOCAL
, а в переменной MASTER_SITE_SUBDIR
укажет логин кластера FreeBSD.
Если дистрибутивные файлы вашего порта постоянно меняются по неизвестным причинам без изменения версий со стороны автора, остаётся только поместить дистрибутив на вашу домашнюю 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-*, где * обозначает путь к файлу, к которому применяется патч, такой как patch-Imakefile или patch-src-config.h.
Используйте |
4.4.1. Общие правила для установки патчей
Файлы патчей хранятся в PATCHDIR
, обычно это files/, откуда они будут автоматически применены. Все исправления должны быть относительны к WRKSRC
. Обычно WRKSRC
является подкаталогом WRKDIR
, каталога, в котором распаковывается distfile. Используйте make -V WRKSRC
для просмотра фактического пути. Имена файлов патчей должны соответствовать следующим правилам:
Избегайте ситуации, когда несколько патчей изменяют один и тот же файл. Например, если и patch-foobar.c, и patch-foobar.c2 вносят изменения в ${WRKSRC}/foobar.c, это делает их хрупкими и затрудняет отладку.
При создании имен для файлов исправлений заменяйте каждое подчеркивание (
_
) на два подчеркивания (__
) и каждый слэш (/
) на одно подчеркивание (_
). Например, чтобы исправить файл с именем src/freeglut_joystick.c, назовите соответствующий исправление patch-src_freeglut__joystick.c. Не называйте исправления как patch-aa или patch-ab. Всегда используйте путь и имя файла в названиях исправлений. Использованиеmake makepatch
автоматически генерирует правильные имена.Патч может изменять несколько файлов, если изменения связаны между собой и патч назван соответствующим образом. Например, patch-add-missing-stdlib.h.
Используйте только символы
[-+._a-zA-Z0-9]
для именования патчей. В частности, не используйте::
как разделитель путей, вместо этого используйте_
.
Минимизируйте количество нефункциональных изменений пробелов в патчах. В мире открытого исходного кода распространена практика, когда проекты используют обширные части кодовой базы, но следуют разным правилам стиля и отступов. При переносе работоспособного функционала из одного проекта для исправления аналогичных участков в другом будьте внимательны: итоговый патч может быть переполнен нефункциональными изменениями. Это не только увеличивает размер репозитория портов, но и затрудняет понимание того, что именно вызвало проблему и какие изменения были внесены.
Если файл необходимо удалить, сделайте это в цели post-extract
, а не как часть исправления.
4.4.2. Ручное создание патчей
Ручное создание патчей обычно не требуется. Предпочтительным методом является автоматическая генерация патчей, как описано ранее в этом разделе. Однако иногда может потребоваться ручное исправление. |
Патчи сохраняются в файлы с именами patch-*, где * указывает на путь к файлу, который патчится, например patch-Imakefile или patch-src-config.h. Патчи с именами файлов, не начинающимися с patch-, не будут применены автоматически.
После изменения файла используется diff(1) для записи различий между оригинальной и изменённой версиями. -u
заставляет diff(1) выводить различия файлов в "унифицированном" формате (unified diffs), которые являются предпочтительным форматом.
% diff -u file.orig file > patch-pathname-file
Для порождении патчей для новых добавляемых файлов используется параметр -N
, который заставляет diff(1) трактовать несуществующие прежде файлы как если бы они существовали, но имели пустое содержимое:
% diff -u -N newfile.orig newfile > patch-pathname-newfile
Использование опции рекурсии (-r
) в diff(1) для создания патчей допустимо, но пожалуйста, проверяйте полученные патчи, чтобы убедиться в отсутствии ненужных данных. В частности, различия между резервными файлами, Makefile, когда порт использует Imake
или GNU configure
, и т.д., являются избыточными и должны быть удалены. Если потребовалось отредактировать configure.in и запустить autoconf
для перегенерации configure
, не включайте различия в configure
(его объем часто достигает нескольких тысяч строк!). Вместо этого определите USES=autoreconf
и возьмите различия для configure.in.
4.4.3. Простая автоматическая замена
Простые замены могут быть выполнены напрямую из Makefile порта, используя режим редактирования на месте утилиты sed(1). Это полезно, когда изменения используют значение переменной:
post-patch: @${REINPLACE_CMD} -e 's|/usr/local|${PREFIX}|g' ${WRKSRC}/Makefile
Довольно часто портируемое программное обеспечение использует соглашение CR/LF в исходных файлах. Это может вызвать проблемы с дальнейшим наложением патчей, предупреждениями компилятора или выполнением скриптов (например, /bin/sh^M не найден
). Для быстрого преобразования всех файлов из CR/LF в просто LF добавьте следующую запись в Makefile порта:
USES= dos2unix
Список конкретных файлов для преобразования может быть указан:
USES= dos2unix DOS2UNIX_FILES= util.c util.h
Используйте DOS2UNIX_REGEX
для преобразования группы файлов во вложенных каталогах. Его аргумент — это совместимое с find(1) регулярное выражение. Подробнее о формате можно узнать в re_format(7). Эта опция полезна для преобразования всех файлов с заданным расширением. Например, преобразовать все исходные файлы кода, оставив двоичные файлы без изменений:
USES= dos2unix DOS2UNIX_REGEX= .*\.([ch]|cpp)
Аналогичной опцией является DOS2UNIX_GLOB
, которая запускает find
для каждого указанного в ней элемента.
USES= dos2unix DOS2UNIX_GLOB= *.c *.cpp *.h
Базовый каталог для преобразования может быть установлен. Это полезно, когда имеется несколько distfiles и в нескольких из них содержатся файлы, требующие преобразования окончаний строк.
USES= dos2unix DOS2UNIX_WRKSRC= ${WRKDIR}
4.4.4. Внесение исправлений при условии
Некоторые порты требуют патчей, которые применяются только для определённых версий FreeBSD или при включении или отключении конкретной опции. Условные патчи указываются путём размещения полных путей к файлам патчей в EXTRA_PATCHES
. Имена файлов условных патчей обычно начинаются с extra-, хотя это и не обязательно. Однако их имена не должны начинаться с patch-. Если это произойдёт, они будут применены безусловно фреймворком, что нежелательно для условных патчей.
.include <bsd.port.options.mk> # Patch in the iconv const qualifier before this .if ${OPSYS} == FreeBSD && ${OSVERSION} < 1100069 EXTRA_PATCHES= ${PATCHDIR}/extra-patch-fbsd10 .endif .include <bsd.port.mk>
Когда для опции требуется патч, используйте opt_EXTRA_PATCHES
и opt_EXTRA_PATCHES_OFF
, чтобы сделать исправление зависимым от опции opt
. Дополнительные сведения см. в Generic Variables Replacement.
OPTIONS_DEFINE= FOO BAR FOO_EXTRA_PATCHES= ${PATCHDIR}/extra-patch-foo BAR_EXTRA_PATCHES_OFF= ${PATCHDIR}/extra-patch-bar.c \ ${PATCHDIR}/extra-patch-bar.h
EXTRA_PATCHES
с директориейИногда для функции требуется множество патчей, в таком случае можно указать EXTRA_PATCHES
на директорию, и все файлы с именем patch-* в ней будут применены автоматически.
Создайте подкаталог в ${PATCHDIR} и переместите в него патчи. Например:
% ls -l files/foo-patches
-rw-r--r-- 1 root wheel 350 Jan 16 01:27 patch-Makefile.in
-rw-r--r-- 1 root wheel 3084 Jan 18 15:37 patch-configure.ac
Затем добавьте это в Makefile:
OPTIONS_DEFINE= FOO FOO_EXTRA_PATCHES= ${PATCHDIR}/foo-patches
Затем фреймворк использует все файлы с именем patch-* в этом каталоге.
4.5. Конфигурирование
Поместите все дополнительные команды, требуемые для настройки, в ваш скрипт configure и сохраните его в подкаталоге scripts. Как отмечено выше, вы можете сделать это целями в файле Makefile и/или скриптами с именами pre-configure или post-configure.
4.6. Обработка пользовательского ввода
Если для построения, конфигурации или установки вашего порта требуется некоторый ввод со стороны пользователя, то вы должны задать переменную IS_INTERACTIVE
в вашем файле Makefile. В случае "ночного построения" это позволит пропустить ваш порт, если пользователь в своем окружении задал переменную BATCH
(и если пользователь установил переменную INTERACTIVE
, то будут строиться только порты, которые требуют взаимодействия с пользователем. Это сэкономит значительное количество времени на части машин, которые постоянно строят порты (смотрите ниже).
При наличии разумных ответов на задаваемые вопросы, подходящих по умолчанию, также рекомендуется проверять переменную PACKAGE_BUILDING
и выключать интерактивный скрипт, если он есть. Это позволит нам строить пакеты для помещения на компакт-диски и FTP-серверы.
Изменено: 18 сентября 2025 г. by Vladlen Popolitov