Дерево портов представляет из себя набор Makefile'ов, по одному для каждой программы, которые управляют:
PLIST
- инструкции по созданию пакета, после того как
программа была собрана
DESCR
- описание программы
distinfo
- размер и checksum архива с исходниками
/usr/ports
.
В иерархии подкаталогов стоит выделить три особенных:
distfiles/
- где храняться скаченные архивы (software
distribution sets) после загрузки из сети
infrastructure/
- все необходимые скрипты и makefiles,
необходимые для инфраструктуры порта
packages/
- бинарные пакеты, собранные системой портов
pkg/
со списком
PLIST и файлом с описанием DESCR.
Также порт может содержать каталог patches/
, где содержатся патчи
для этого порта, и files/
для других дополнительных файлов.
Когда пользователь запускает make(1)
в подкаталоге того или иного порта, система рекурсивно просматривает свое дерево
зависимостей, проверяет, установлены ли требуемые зависимости, собирает и
устанавливает любые недостающие зависимости, а затем продолжает сборку
нужного порта.
Весь процесс сборки происходит внутри так называемого рабочего каталога
(working directory), который создает порт.
Обычно это ${WRKOBJDIR}
, для которой по умолчанию используется
/usr/ports/pobj
, но вы можете переопределить это
(см. настройка системы портов).
Дерево портов связано с версиями OpenBSD. Не стоит ожидать, что порты из дерева портов -current будут работать в release или -stable. Если вы используете -current, вам нужны и -current base system и дерево портов -current. Поскольку в -stable не вносятся навязчивые (intrusive) изменения, дерево портов release и -stable являются совместимыми.
Еще одна распространенная ошибка - отсутствующая установка X11. Даже если порт, который вы пытаетесь собрать, не имеет прямой зависимости к X11, для его подпакета или его зависимостей могут потребоваться headers и библиотеки X11. Сборка портов в системах без X11 не поддерживается.
Более исчерпывающая информация по теме системы портов находится в man-страницах:
Источник | Формат | Flavor | |||
---|---|---|---|---|---|
release | -stable | snapshots | -current | ||
Зеркала | .tar.gz | ✓ | ✗ | ✓ | ✗ |
AnonCVS | cvs checkout | ✓ | ✓ | ✗ | ✓ |
Обратите внимание на файл ports.tar.gz
, который можно найти на
наших зеркалах.
$ cd /tmp $ ftp https://cdn.openbsd.org/pub/OpenBSD/$(uname -r)/{ports.tar.gz,SHA256.sig} $ signify -Cp /etc/signify/openbsd-$(uname -r | cut -c 1,3)-base.pub -x SHA256.sig ports.tar.gzЕго надо распаковать в каталог
/usr
, что приведет к созданию
/usr/ports
и множества других подкаталогов внутри него.
# cd /usr # tar xzf /tmp/ports.tar.gzСнапшоты, доступные на наших зеркалах, генерируются ежедневно из дерева портов -current. Вы можете найти их в каталоге
/pub/OpenBSD/snapshots/
.
Если вы решили установить снапшот того или иного дерева портов, вы должны
использовать и соответствующий снапшот OpenBSD.
Не забвайте синхронизировать установленное дерево портов с используемой OpenBSD!
Для получения дополнительной информации о загрузке дерева портов через CVS прочитайте страницу, посвященную AnonCVS. Там можно найти список доступных серверов и ряд полезных примеров.
Поскольку у проекта OpenBSD нет ресурсов для полного review всего исходного
кода в дереве портов, вы можете предпринять нескоторые меры предосторожности,
при помощи соответствующих настроек.
Система портов, которую иногда называют «инфраструктурой портов», позволяет
почти полностью собирать порты от имени обычного пользователя, и лишь некоторые
шаги, которые требуют привилегий суперпользователя, от имени root (например,
команда make install
). Подробнее о том, как настроить разделение
привилегий, рассказывается в man-странице
bsd.port.mk(5).
Можно использовать read-only дерево портов при помощи разделения от каталогов, в которые производится запись во время сборки порта:
WRKOBJDIR
. Ее значение
указывает на каталог, который будет содержать рабочие каталоги.
DISTDIR
.
PACKAGE_REPOSITORY
.
/etc/mk.conf
:
WRKOBJDIR=/usr/obj/ports DISTDIR=/usr/distfiles PACKAGE_REPOSITORY=/usr/packagesПри желании вы также можете изменить владельца (ownership) этих каталогов на свое локальное имя пользователя и группу, чтобы система портов могла создавать базовые рабочие каталоги от имени обычного пользователя. Опять же, порты могут быть собраны от имени обычного пользователя, но установленны должны быть только пользователем root или при помощи doas(1).
make search key="searchkey"
как показано в примере ниже:
$ cd /usr/ports $ doas pkg_add portslist $ make search key=rsnapshot Port: rsnapshot-1.4.2 Path: net/rsnapshot Info: remote filesystem snapshot utility Maint: Antoine Jacoutot <ajacoutot@openbsd.org> Index: net sysutils L-deps: B-deps: devel/autoconf/2.69 devel/automake/1.15 devel/metaauto net/rsync R-deps: devel/p5-Lchown net/rsync Archs: anyРезультат поиска содержит не только название порта, но и предоставляет некоторую дополнительную информацию: PATH к порту, короткое описание, имя и почтовый адрес мейнтейнера, ключевые слова, связанные с портом, library/build/runtime зависимости и список архитектур, на которых порт поддерживается и работает.
Описанный способ очень прост. Тут просто запускается awk(1), который
парсит index файл порта.
Порт под названием «sqlports» напротив позволяет осуществлять очень
детальный поиск при помощи поиска в базе данных. Это база данных SQLite,
но практически любой формат базы данных может быть создан при помощи
инфраструктуры портов.
Порт sqlports
включает в себя скрипт для создания базы
данных, который можно использовать для создания баз данных различных
форматах.
Просто установите пакет sqlports
, чтобы попробовать.
Пример сеанса может выглядеть так:
$ sqlite3 /usr/local/share/sqlports sqlite> SELECT FULLPKGNAME,COMMENT FROM Ports WHERE COMMENT LIKE '%statistics%'; pg_statsinfo-3.3.0p0|monitor PostgreSQL activity & statistics kactivities-stats-5.51.0|statistics for the KDE Activity concept p5-Devel-Cover-Report-Clover-0.35|backend for Clover reporting of coverage statistics mailgraph-1.14p1|RRDtool frontend for Postfix statistics R-3.5.1p1|powerful math/statistics/graphics language p5-Math-VecStat-0.08p0|provides basic statistics on numerical vectors py-probstat-0.912p8|probability and statistics utilities for Python py-statistics-1.0.3.5|port of Python 3.4 statistics module to Python 2 darkstat-3.0.719p1|network statistics gatherer with graphs pfstat-2.5p2|packet filter statistics visualization rtg-0.7.4p12|SNMP statistics monitoring system slurm-0.4.3|network traffic monitor and statistics tcpstat-1.5p0|report network interface statistics libstatgrab-0.91p3|system statistics gathering library p5-Unix-Statgrab-0.109p0|interface to libstatgrab system statistics library diffstat-1.62|accumulates and displays statistics from a diff file fragistics-1.7.0p2|Quake 3 statistics program drupal7-google_analytics-1.2p2|add the Google Analytics web statistics to your site dstat-0.5p0|dwm status bar statistics kdf-4.14.3p4|KDE storage device statistics libsysstat-0.4.1|library used to query system info and statistics qdirstat-1.4p1|Qt-based directory statistics sqlite>Выше описан все же достаточно простой поиск. При помощи SQL можно искать практически все, что угодно, включая зависимости, флаги настройки, shared libraries и т.д.
devel/autoconf/2.69
,
devel/automake/1.15
, devel/metaauto
и net/rsync
.
Выполнение следующей команды подразумевает, что вы настроили
PORTS_PRIVSEP, как описано в man-странице
bsd.port.mk.
$ cd /usr/ports/net/rsnapshot $ make install ===> Checking files for rsnapshot-1.4.2 >> Fetch https://github.com/rsnapshot/rsnapshot/archive/1.4.2/rsnapshot-1.4.2.tar.gz 100% |**************************************************| 365 KB 00:02 >> (SHA256) rsnapshot-1.4.2.tar.gz: OK ===> rsnapshot-1.4.2 depends on: metaauto-* - not found ===> Verifying install for metaauto-* in devel/metaauto ===> Checking files for metaauto-1.0p1 [...] ===> Installing metaauto-1.0p1 from /usr/ports/packages/amd64/all/ metaauto-1.0p1: ok ===> Returning to build of rsnapshot-1.4.2 ===> rsnapshot-1.4.2 depends on: metaauto-* -> metaauto-1.0p1 ===> rsnapshot-1.4.2 depends on: autoconf-2.69 - not found [...] ===> Returning to build of rsnapshot-1.4.2 ===> Extracting for rsnapshot-1.4.2 ===> Patching for rsnapshot-1.4.2 [...] ===> Compiler link: clang -> /usr/bin/clang ===> Compiler link: clang++ -> /usr/bin/clang++ ===> Compiler link: cc -> /usr/bin/cc ===> Compiler link: c++ -> /usr/bin/c++ ===> Generating configure for rsnapshot-1.4.2 ===> Configuring for rsnapshot-1.4.2 [...] ===> Building for rsnapshot-1.4.2 [...] ===> Faking installation for rsnapshot-1.4.2 [...] ===> Building package for rsnapshot-1.4.2 [...] Link to /usr/ports/packages/amd64/all/rsnapshot-1.4.2.tgz Link to /usr/ports/packages/amd64/ftp/rsnapshot-1.4.2.tgz Link to /usr/ports/packages/amd64/cdrom/rsnapshot-1.4.2.tgz ===> rsnapshot-1.4.2 depends on: p5-Lchown-* - not found [...] ===> Installing rsnapshot-1.4.2 from /usr/ports/packages/amd64/all/ rsnapshot-1.4.2: ok
Как вы видете, много делается автоматически. Система портов загружает, распаковывает
и накладывает патчи на исходники, настраивает и собирает (компилирует) их,
устанавливает файлы в fake каталог, создает пакет (или даже список пакетов) и
устанавливает этот пакет в вашу систему (обычно в /usr/local/
).
И все это проделывается рекурсивно для всех зависимостей порта.
Обратите внимание на строки
"===> Verifying install for ...
" и
"===> Returning to build of ...
"
в приведенном выше выводе, указывающие на обход дерева зависимостей.
Если вы хотите установить какую-то программу, а она уже установленна
в вашей системе, но установленна её старая версия,
используйте make update
вместо make install
.
Это запустит pkg_add(1)
с флагом -r
.
Большие программы потребуют много системных ресурсов для сборки. Если вы получаете ошибки типа «out of memory» при попытке сборки такого порта, это обычно присходит по одной из двух причин:
ulimit
или csh команды limit
.
$ make clean ===> Cleaning for rsnapshot-1.4.2По умолчанию зависимости workdir автоматически очищаются. Вы можете удалить установленные пакеты, которые были необходимы только для сборки порта.
# pkg_delete -a p5-Module-Build-0.4224: ok autoconf-2.69p2:automake-1.15.1: ok autoconf-2.69p2: ok metaauto-1.0p1: ok Read shared items: okЕсли вы хотите удалить исходники порта (source distribution set(s) of the port), сделайте следующее:
$ make clean=dist ===> Cleaning for rsnapshot-1.4.2 ===> Dist cleaning for rsnapshot-1.4.2Если вы компилировали несколько версий одного и того же порта, вы можете очистить рабочие каталоги всех этих версий одновременно:
$ make clean=flavorsВы также можете очищать все после каждой сборки, изменив
BULK
с auto
на Yes
.
$ make package BULK=Yes
$ make uninstall ===> Deinstalling for rsnapshot-1.4.2 rsnapshot-1.4.2: ok Read shared items: okЭто запустит pkg_delete(1), который удалит соответствующий пакет из системы. Если вы хотите избавиться от только что собранных пакетов, это можно сделать следующим образом:
$ make clean=packages ===> Cleaning for rsnapshot-1.4.2 rm -f /usr/ports/packages/amd64/all/rsnapshot-1.4.2.tgz
Первый механизм называется flavors. Flavor обычно указывает на определенный набор параметров компиляции. Например, некоторые приложения имеют flavor «no_x11», который предназначен для использования в системах без X. Некоторые оболочки имеют «статический» flavor, который создает статически связанную версию. Существуют порты, которые имеют разные flavors для их сборки с использованием различных графических инструментов. Другие примеры включают в себя поддержку различных форматов баз данных, различных параметры сети (SSL, IPv6, ...), различных размеров бумаги и т.д.
Подводим итог: Скорее всего, вы будете использовать flavors, если пакет не предоставляет (не поддерживает) flavor, который вам нужен. В этом случае вы можете указать желаемый flavor и собрать порт самостоятельно.
Большинство flavors портов имеют свой собственный рабочий каталог во время компиляции, и каждый flavor собирается в пакете с соответствующим именем, чтобы избежать путаницы. Чтобы увидеть различные flavor того или иного порта, посмотрите в его подкаталог и выполнить команду:
$ make show=FLAVORSВы также можете посмотреть файлы
DESCR
порта, где более подробно
объясняются доступные flavors.
Второй механизм называется subpackages. Мэйнтейнер может решить создать подпакеты (subpackages) для разных частей одной программы, если они могут быть логически разделены. Вы будете часто видеть subpackages для клиентской части и серверной части программы. Иногда обширная документация упакована в отдельный subpackage, поскольку она занимает много места на диске. Другим примером могут быть дополнительный функционал программы, который тянет кучу зависимостей, и который часто упаковываются отдельно. Мэйнтейнер также решит, какой subpackage является основным, и будет установлен по умолчанию. Другими примерами являются обширные тестовые наборы, которые поставляются с программами, отдельные модули с поддержкой всего возможного и т.д.
Подводим итог:
Некоторые порты могут быть разделены на несколько частей (или пакетов).
make install
установит только главную из них (main subpackage).
Список packages, на которые разделен порт, можно увидеть при помощи команды:
$ make show=PKGNAMES
make install
установит только главный subpackage.
Для того, чтобы установить их всех, используй команду:
$ make install-allСписок subpackages, доступных для порта, можно увидеть при помощи команды:
$ make show=MULTI_PACKAGESМожно выбрать какие подпакеты (subpackage(s)) установить из дерева портов. После некоторых тестов эта процедура просто вызовет pkg_add(1) для установки нужного subpackage(s).
# env SUBPACKAGE="-server" make installsubpackages механизм обрабатывает только packages. Он не изменяет никакие параметры конфигурации перед сборкой порта. Вы должны использовать flavors для этой цели.
/usr/ports/infrastructure/bin/dpb
.
dpb(1) ожидает список портов
для сборки и автоматически собирает их все параллельно в оптимальном порядке.
Он также может использовать несколько машин для сборки, а также создает
подробные build-logs, которые можно будет найти в /usr/ports/logs
,
и которые можно будет использовать для troubleshooting.
# /usr/ports/infrastructure/bin/dpb -P ~/localportsЭта команда запустит dpb, который прочтет список pkgpaths из
~/localports
и соберет все перечисленные там пакеты.
Он также может установить пакеты после их сборки.
Файл ~/localports
выглядит следующим образом:
net/rsync www/mozilla-firefox editors/vimЕсли вы не передадите список портов для сборки в командной строке или через
-P
или -I
,
dpb(1) соберет все порты в
дереве портов. При запуске от пользователя root, dpb автоматически отбрасывает
привилегии, присвоенные пользователям для загрузки файлов с исходниками
и сборки портов. Это рекомендуемый способ его использования, но он также
может запускаться от имени обычного пользователя.
Кроме того, утилита proot(1)
может использоваться для дальнейшей изоляции build операций.
Это означает, что все, что вам нужно сделать, это убедиться, что вы проверили правильный branch дерева портов и собрали необходимые программы из него. Вы можете поддерживать свое дерево в актуальном состоянии (up to date) при помощи CVS и подписаться на почтовую рассылку ports-changes, чтобы получать уведомления о безопасности, связанные портами.
Если вы хотите собрать свой собственный подписанный пакет, вам сначала понадобится создать/сгенерировать пару ключей.
# signify -Gns /etc/signify/my-pkg.sec -p /etc/signify/my-pkg.pubЗамечание по поводу имен: ключи, используемые для подписи пакетов, должны заканчиваться на
pkg
.
Существующие пакеты могуть быть подписаны при помощи pkg_sign(1) после их сборки.
# cd /usr/ports/packages/$(uname -p) # pkg_sign -s signify2 -s /etc/signify/my-pkg.sec -o signed -S allВ случае установки такого пакета на другой машине, public key
my-pkg.pub
должен быть скопирован туда в каталог
/etc/signify
.
$ cd /usr/ports/archivers/unzip $ make show=MAINTAINERЕсли мэйнтейнер не указан, или же если по той или иной причине с ним не получается связаться, отправьте письмо в рассылку ports@openbsd.org.
Так или иначе, не забудьте предоставить следующую информацию:
sysctl -n kern.version
.
/usr/ports/CVS/Tag
,
покажие его содержимое. Отсутствие этого файла говорит о том, что
используется дерево портов -current.
portslogger
,
находящийся в /usr/ports/infrastructure/bin
.
Пример может выглядеть так:
$ mkdir ~/portlog $ cd /usr/ports/archivers/unzip $ make 2>&1 | /usr/ports/infrastructure/bin/portslogger ~/portlogПосле этого, в каталоге
~/portlog
должен быть файл журнала
сборки, который вы можете отправить мэйнтейнеру порта. Также убедитесь,
что вы не используете никаких своих специальных параметров во время сборки,
указанных например в /etc/mk.conf
.
В качестве альтернативы вы можете сделать следующее:
gcc -save-temps
.
egdb
:
# pkg_add gdbДля некоторых архитектур есть debug-пакеты (например, если порт называется
neomutt-20201127
, debug-пакет будет называться
debug-neomutt-20201127
).
Эти пакеты содержат файлы с необходимой для отладки информацией (debug symbols);
GDB знает, как загружать эти файлы автоматически. Debug-пакет должен
соответствовать основному пакету: если вы используете snapshots, может
потребоваться обновить пакет, чтобы быть увереным, что оба пакета собирались
вместе (относятся к той же сборке). Устанавливается debug пакет, как и обычно,
при помощи pkg_add:
# pkg_add debug-neomuttЕсли debug-пакет недоступен, вы сможете увидеть лишь имена функций (но не более) из дампа ядра; иногда этого достаточно, чтобы разобраться в проблеме.
Порт может быть собран с отладочной информацией (debug symbols) на
специальной ad-hoc основе (полезно на архитектурах, для которых debug-пакеты
обычно не собираются) путем сборки порта при помоши make DEBUG=-g
.
Сначала вам нужно будет очистить существующую сборку и пакеты (а иногда даже
могут возникать проблемы при сборке, если вы сначала не удалите/очистите все
оставшееся с прошлой сборки).
Если интересующий пакет является библиотекой или зависит от других портов,
вам, возможно, придется удалить всю цепочку, чтобы сделать это.
Также может быть полезно отключить оптимизацию (добавить -O0
в DEBUG).
$ cd /usr/ports/math/moo $ make clean; make DEBUG="-g" repackage; make reinstallЕсли у вас есть файл дампа ядра, скормите его GDB и вы получите backtrace:
$ egdb neomutt neomutt.core GNU gdb (GDB) 7.12.1 Copyright (C) 2017 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-unknown-openbsd6.8". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from /usr/local/bin/neomutt...Reading symbols from /usr/local/bin/.debug/neomutt.dbg...done. done. [New process 577437] Core was generated by `neomutt'. Program terminated with signal SIGABRT, Aborted. #0 _thread_sys_poll () at /tmp/-:3 3 /tmp/-: No such file or directory. (gdb) bt #0 _thread_sys_poll () at /tmp/-:3 <...> #9 0x00000b3f1d5ec847 in main (argc=<optimized out>, argv=0x7f7ffffc8a08, envp=<optimized out>) at ../neomutt-20201127/main.c:1236 (gdb) qДля программ setuid/setgid дампы ядра отключены по умолчанию, см. sysctl(8), чтобы узнать, как их разрешить. В качестве альтернативы вы можете загрузить программу при помощи отладчика, задать необходимые аргументы и сделать
run
:
$ egdb neomutt <...> (gdb) set args -d 2 (gdb) run +<...>Вы вернетесь в отладчик при получении определенных сигналов. (в большинстве случаев - в том месте, где произойдет сбой).
Чтобы включить debug-пакеты в обычной bulk сборке для порта, добавьте
"DEBUG_PACKAGES=${BUILD_PACKAGES}
" в Makefile.
Это установит DEBUG во время сборки, а на packaging этапе автоматически
отделит символы отладки от основных бинарников.
Он также попытается сжать символы при помощи dwz; этот шаг срабатывает не
всегда; в таком случае его можно переопределить при помощи "DWZ=:
".
Если вы регулярно занимаетесь разработкой портов, установка значения
"INSTALL_DEBUG_PACKAGES=Yes
" в файле /etc/mk.conf, что приведет к
автоматической установке недавно собранных debug-пакетов.
Пожертвования железа может помочь в тестировании портов на поддерживаемых OpenBSD платформах.