CITKIT.ru - свободные мысли о свободном софте
Деловая газета CitCity.ru Библиотека CITForum.ru Форумы Курилка
Каталог софта Движение Open Source Дискуссионный клуб Дистрибутивы Окружение Приложения Заметки Разное
23.06.2017

Последние комментарии

ОСТОРОЖНО: ВИНДОФИЛИЯ! (2250)
24 December, 22:53
Kubuntu Feisty (15)
24 December, 18:42
Один на один с Windows XP (3758)
24 December, 11:46

Каталог софта

Статьи

Дискуссионный клуб
Linux в школе
Open Source и деньги
Open Source и жизнь
Windows vs Linux
Копирайт
Кто такие анонимусы
Лицензии
Нетбуки
Нужен ли русский Linux?
Пользователи
Дистрибутивы
Идеология
Выбор дистрибутива
Archlinux & CRUX
Debian
Fedora
Gentoo
LFS
LiveCD
Mandriva
OpenSolaris
Slackware
Zenwalk
Другие линуксы
BSD
MINIX
Движение Open Source
История
Классика жанра
Окружение
shell
Библиотеки UI
Графические среды
Шрифты
Приложения
Безопасность
Управление пакетами
Разное
Linuxformat. Колонки Алексея Федорчука
Заметки
Блогометки
Файловые системы
Заметки о ядре

Приложения :: Управление пакетами

Управление портами в BSD-системах

В предыдущий заметке были рассмотрены инструменты для установки прекомпилированных бинарных пакетов. Однако этот метод не является основным при наращивании функциональности операционок BSD-клана: средства пакетного менеджмента суть производные систем сборки пакетов из исходников.

Таковых в BSD две: система портов, зародившаяся во FreeBSD и заимствованная в OpenBSD и DragonFlyBSD, и система pkgsrc, разработанная для NetBSD, но ныне превратившаяся в кросс-платформенное средство. Предметом настоящей заметки будет первая из них, рассмотренная на примере DragonFlyBSD. Однако все сказанное приложимо и к исходным портам FreeBSD, и к аналогичной системе OpenBSD.

О портах FreeBSD написано немало. И для любого пользователя этой системы обращение с портами - дело своеобычное, прочно вошедшее в привычку. В концептуальном плане немало общего с портами найдут и пользователи Source Based дистрибутивов Linux (еще бы - ведь и портежи Gentoo, и ABS из Archlinux, и Sorcery из Sorcerer сотоварищи возникли под их влиянием). Однако для пользователей пакетных дистрибутивов Linux и, тем более, тех, кто приобщается к POSIX'визму впервые, концепция портов может показаться необычной.

Итак, система портов - это набор правил для отыскания в Сети исходников устанавливаемых программ, их получения на локальную машину, конфигурирования, сборки (компиляции и линковки), инсталляции в файловую систему и, возможно, постинсталляционного конфигурирования. То есть по этим правилам выполняется весь тот цикл действий, которые мы проделываем при ручной сборке любой программы (три волшебных заклинания ./configure, make, make install), но - в автоматическом режиме. Однако плюс к этому важный компонент системы портов - средства отслеживания зависимостей, как "жестких", обязательных, так и "мягких", опциональных, коррекции последних в ту или иную сторону, ну и, конечно же, автоматического удовлетворения тех и других.

Возможности системы портов могут показаться просто волшебными, особенно тем, кому знакомы мучения с зависимостями при использовании чистого rpm, незамутненного никакими apt-get или yum. За счет чего же они реализуются?. За счет обычной утилиты make (или, точнее, BSD make) - весьма близкого аналога GNU make, знакомого всем пользователям Linux, хотя бы единожды в жизни собиравшим программы из исходников. Правда, следует помнить, что это все-таки разные программы, и при установке некоторых портов как зависимость может потребоваться именно GNU make - хотя вручную они прекрасно соберутся и посредством BSD make.

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

Файлы, составляющие порт программы - простые текстовые файлы, которые можно просмотреть утилитами типа less или more, можно (а при необходимости - и нужно) поправить в обычном текстовом редакторе. То есть, не смотря на фантастические результаты работы системы портов, сам порт не содержит в себе ничего сверхъестественного, недоступного пониманию обычного пользователя.

Обязательный набор любого порта составляют четыре файла: distinfo, pkg-descr, pkg-plist и Makefile. первый содержит краткую информацию о пакете, послужившем предметом портирования: имя тарбалла исходников, его размер и контрольную сумму. Например, для текстового редактора joe (порт joe-devel, описывающий установку его версии 3.X) это выглядит так:

MD5 (joe-3.1.tar.gz) = 2a6ef018870fca9b7df85401994fb0e0
SIZE (joe-3.1.tar.gz) = 381201

Файл distinfo нужен на стадии получения исходных текстов портированного пакета и проверки его подлинности.

Содержание файла pkg-descr представляет собой краткую (как правило, в один абзац) характеристику портируемой программы, из которой обычно легко понять ее назначение. Обычно здесь же указываются URL мастер сайта проекта и имя и e-mail сборщика (майнтайнера) порта. Пример для того же joe-devel:

	JOE is the professional freeware ASCII text screen editor for UNIX.
	It makes full use of the power and versatility of UNIX...
	...
	
	WWW: http://sourceforge.net/projects/joe-editor/
	
	-Pete
	petef@databits.net
	

Файл pkg-descr предназначен в основном для ориентации пользователя в развесистой кроне дерева портов.

Ну а pkg-plist - это просто список файлов, которые соберутся во время установки порта, и указание путей к каталогам, куда они будут инсталлированы. Во все том же joe-devel его содержание примерно такое:

	bin/jmacs
	bin/joe
	bin/jpico
	bin/jstar
	bin/rjoe
	...
	

Пути к файлам указываются относительно некоторого каталога, представляющего корень всех установленных портов, в большинстве случаев по умолчанию - /usr/local. Содержимое файла pkg-plist требуется для регистрации порта в базе данных установленных пакетов - в var/db/pkg, что в дальнейшем позволяет отслеживать зависимости иных пакетов, удалять и обновлять инсталлированные порты.

Наконец, сам Makefile - это главный файл каждого порта. Это в сущности набор переменных, значения которых (продолжаю приводить примеры для joe-devel):

  • имя сортируемого пакета, номер его текущей версии (соответствующей версии разработчика пакета), ревизии порта (определяемой майнтайнером порта):
  • 	PORTNAME=       joe
    	PORTVERSION=    3.1
    	PORTEPOCH=      1
    	
  • категории, то есть семейства программ, к которой порт относится:
  • 	CATEGORIES=     editors
    	
  • URL мастер-сайта портируемого пакет, или иного сервера, с которого можно получить его исходники, а также имя каталога, в котором он там находится; обращаем внимание - значение первой переменной определяется также через некую переменную, а сами адреса перечислены в одном из группы файлов, общих для всей системы (о чем речь пойдет дальше):
  • 	MASTER_SITES=   ${MASTER_SITE_SOURCEFORGE}
    	MASTER_SITE_SUBDIR=     joe-editor
    	
  • e-mail майнтайнера порта и очень краткое его описание:
  • 	MAINTAINER=     petef@FreeBSD.org
    	COMMENT=        Development version of Joe's own editor
    	
  • некоторых дополнительных строк, описывающих, например, модель имяобразования порта, и т.д.

Эти строки составляют, так сказать, первую секцию Make-файла, построенную однотипно для всех портов. Дальше же описываются вещи, специфичные для конкретного пакета. В первую очередь это его зависимости, подчас с разделением на категории - зависимости для построения, зависимости для запуска, зависимости от библиотек, и так далее. Фигурируют тут и опции конфигурирования пакета (при исполнении сценария ./configure), которые также могут добавить или убавить зависимостей. В общем, содержимое второй части Make-файла проще посмотреть для интересующего пакета, нежели описывать в деталях.

Наконец, третья часть Make-файла - строки, подобные этой:

.include 

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

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

Все файлы, составляющие порт, объединены в одном каталоге, носящем имя портируемой программы, без версии, например, joe. В ряде случаев для обеспечения зависимостей необходимо поддерживать две версии программы - классическими примерами являются пары Gtk1/Gtk2 и Freetype1/Freetype2. В таком случае для каждой из них создается собственный каталог с набором портообразующих файлов.

Кроме того, в портах, как правило, представлена последняя версия программы, именуемая разработчиком стабильной (насколько уж она отвечает своему титулу - это другой вопрос). Однако в ряде случаев наряду с ней может присутствовать и версия разрабатываемая - может быть, не столь прилизанная, но более функциональная. И как раз редактор joe тому примером: под этим именем в дерево портов присутствует древняя (уж даже не помню, какого года розлива) версия 2.8, давно прекратившая свое развитие. Современная (3.1) же версия этого редактора, поддерживающая UTF-8, подсветку синтаксиса и имеющая множество иных усовершенствований, в системе портов называется joe-devel.

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

Индивидуальные порты объединяются в категории по назначению портируемых программ: editors, audio, graphics, и так далее. Каждая такая категория образует собственный каталог в дереве портов (/usr/ports), а индивидуальные порты входят в них как подкаталоги. Так что в полном виде номенклатура порта выглядит так: editors/joe-devel. А уж каталоги, соответствующие категориям, и образуют собой дерево системы портов.

Кроме индивидуальных портов, в составе дерева портов присутствуют так называемые метапорты. Это - крупные программные комплексы, такие, как XFree86, Xorg, KDE и GNOME. И их make-файлы описывают не процесс сборки отдельных пакетов, а лишь их набор, взаимоотношения и последовательность сборки. А уж за саму сборку каждого компонента отвечает его собственный порт.

Бывает, что на базе одного такого программного комплекса создается несколько метапортов. Например, для KDE существует два метапорта: x11/kde3 и x11/kde-lite. Первый охватывает все компоненты KDE, второй же - лишь наиболее существенные.

Таково в общих чертах устройство системы портов FreeBSD, без всяких изменений перенесенной в DragonFlyBSD. Однако, не смотря на внешнее сходство, доходящее до тождества, внутренне это - весьма разные операционки. И потому отнюдь не все порты FreeBSD обязаны корректно собираться в DragonFlyBSD. Что и вызвало необходимость в создании собственной системы портов - dfports, которая охватывает именно такие пакеты. Важнейшими, пожалуй, тут будут порты Иксовых библиотек - x11/XFree86-4-libraries и x11/xorg-libraries - ни тот, ни другой из портов FreeBSD в DragonFly не строится. На устройстве их я останавливаться не буду - оно ничем не отличаются от своего прототипа. Отличия заключены лишь в патчах, прилагаемых к каждому порту dfports.

Теперь перейдем к практической части - как распорядиться доставшимся по наследству богачеством? Конечно, для начала неплохо бы им обзавестись - ни порты FreeBSD, ни даже dfports в состав дистрибутива DFBSD, распространяемого на CD, не входят.

Актуальный срез дерева портов FreeBSD в виде тарбалла (ports.tar.gz, около 25 Мбайт) можно скачать с любого ftp-сервера проекта, после чего развернуть его в каталоге /usr обычным образом:

$ cd /usr 
$ tar xzvf path_to/ports.tar.gz

Дальнейшее же обновление его можно производить с помощью cvsup. Прототипы соответствующих конфигов - также на серверах проекта. Имеются они и дистрибутиве - в каталоге /usr/share/examples/cvsup. Описывать их все было бы скучно, поэтому для примера приведу свой:

$ less /root/free-ports-supfile

# Ports Collections of FreeBSD
*default host=cvsup.no.FreeBSD.org
*default base=/usr
*default prefix=/usr
*default release=cvs tag=.
*default delete use-rel-suffix
# If your network link is a T1 or faster, comment out the following line.
#*default compress
## Ports Collection.
#
# The easiest way to get the ports tree is to use the "ports-all"
# mega-collection.  It includes all of the individual "ports-*"
# collections,
ports-all

Разумеется, все порты скачивать отнюдь не обязательно - только людям с весьма специфическими интересами потребуются средства поддержки китайского, вьетнамского, арабского и прочих языков, составляющие весомую долю в дереве. И потому вместо указания ports-all можно просто перечислить необходимые категории.

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

Следующий шаг - настройка общих средств обращения с портами. Она осуществляется редактированием файла /etc/make.conf. Многие его переменные имеют отношение и к системе портов тоже. Это, например, указание на версию компилятора CCVER и определение его флагов CPUTYPE, CFLAGS и CXXFLAGS (но не COPTFLAGS - эта переменная влияет только на флаги компиляции ядра). Подавляющее большинство портов успешно собирается при значении CFLAGS=-O3 - другое дело, насколько это оправданно с точки зрения повышения быстродействия (по моим наблюдениям - в большинстве случаев неоправданно абсолютно).

Другие же переменные из /etc/make.conf относятся только к системе портов. Это в первую очередь дублирующий состав - адреса сайтов для скачивания исходников, которые должны проверяться прежде тех, что определены для портов в целом (или в Make-файлов конкретных портов). Далее - адреса ftp- и http-прокси. И наконец - каталоги для помещения временных продуктов компиляции при построении порта, о чем еще будет говориться далее.

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

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

$ cd /usr/ports/editors/joe

и отдаче команды make в сопровождении двух волшебных слов (targets, целей сборки):

$ make install clean

Что влечет за собой такие последствия:

  • соединение с одним из серверов, указанных в конфигурационном файле /etc/make.conf, /usr/ports/Mk/bsd.port.mk или make-файле порта, и получение с него тарбалла исходников пакета;
  • проверка контрольной суммы полученного тарбалла;
  • распаковка тарбалла в подкаталог port_name/work/pkg_name;
  • наложение, в случае необходимости, на дерево исходников патчей, специфичных для данного порта (располагающихся, как уже говорилось, в подкаталоге (port_name/files);
  • конфигурирование пакета, то есть выполнение сценария ./configure (в корне дерева исходников, то есть port_name/work/pkg_name), и определение его зависимостей;
  • обработка портов, необходимых для сборки и/или функционирования данного, осуществляемая по той же схеме;
  • компиляция пакета и его линковка с потребными библиотеками;
  • инсталлирование, то есть инкорпорация новообразованных бинарников в должные ветви дерева файловой системы DFBSD, и регистрация порта в базе данных - /var/db/pkg, той самой, где фиксируются и пакеты, установленные из бинарников (см. соответствующую заметку);
  • очистка порта от промежуточных продуктов построения порта, то есть попросту уничтожение каталога port_name/work.

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

  • fetch - получение исходников и помещение их в каталог /usr/ports/distfiles;
  • checksum - проверка контрольной суммы;
  • extract - распаковка тарбалла исходников в подкаталог potr_name/work (если место для промежуточных продуктов компиляции не переопределено в переменной WRKDIRPREFIX файла /etc/make.conf);
  • patch - наложение патчей, если таковые предусмотрены в составе порта, на дерево исходников;
  • configure - выполнение сценария конфигурирования в корне дерева исходников;
  • build - компиляция и линковка пакета;
  • install - инсталляция собранных компонентов и регистрация пакета в базе данных /var/db/pkg;
  • clean - очистка дерева исходных текстов от промежуточных продуктов сборки.

Кроме этого, существует интегральная цель all - именно она выполняется по умолчанию, если команда make дана без указания целей вообще. Одна включает в себя такую последовательность действий:

fetch checksum extract patch configure build

то есть все, вплоть до построения порта, но не его инсталляцию (цель install) и очистку (clean). Дело в том, что два последних действия являются не только не обязательными, но иногда и нежелательными. Так, инсталляция построенного порта не требуется, если мы собираем бинарные пакеты для автономного распространения (в том числе и не на этой машине). Для чего предусмотрена специальная цель -

$ make package

Именно таким способом создаваются обычно существующие бинарные пакеты для FreeBSD и DragonFlyBSD.

Сохранение же дерева исходников (то есть отказ от цели clean) может потребоваться для целей отладки и внесения собственных изменений в них. Правда, в любом случае его желательно освободить от продуктов компиляции, то есть объектных модулей (файлов вида *.o). Для чего команду

$ make clean

достаточно выполнить, перейдя предварительно в подкаталог port_name/work/pkg_name. Нужно только иметь ввиду, что сохранение рабочих подкаталогов для многих портов, особенно таких крупных, как x11/kde, способно очень быстро загромоздить ветвь /usr/ports. В этом одна из причин того, что последнюю целесообразно помещать на собственном дисковом разделе.

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

$ make install
Легко догадаться, что описанная схема будет успешно функционировать только при условии подключения к Сети: если такового не имеется - сразу же вслед за командой make ... последует сообщение об ошибке вида

...Host not found
=> Couldn't fetch it - please try to retrieve this
=> port manually into /usr/ports/distfiles/ and try again.
*** Error code 1

Однако оно и подсказывает решение - нужно получить каким-либо образом исходники программы и поместить их в каталог /usr/ports/distfiles/, специально предназначенный для хранения оных (он возникает автоматически при первом же использовании системы портов и проверяется в первую очередь - до обращения к мастер-сайтам порта). Как это сделать?

Если мы в пределах физической досягаемости имеем BSD-машину, то все просто: отправляемся к ней, переходим в каталог нужного порта и даем команду

$ make fetch

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

$ make fetch-recursive

Правда, тут следует учитывать одно обстоятельство. Зависимости, определяемые при построении порта по полной программе, берутся из результатов реального его конфигурирования (выполнения сценария configure. При исполнении же цели fetch-recursive источником для определения зависимостей будет база данных установленных пакетов - /usr/db/pkg. Так что результаты обеих процедур не обязательно будут идентичными. Хотя на практике этим обстоятельством в большинстве случаев можно пренебречь.

Однако предположим, что доступа в сетевой BSD-машине у нас нет, и штатными средствами системы портов для получения исходников мы воспользоваться не можем. Тоже не смертельно - можно получить список необходимых файлов исходников, и скачать их любым ftp-клиентом - хоть из под Windows. Для единичного тарбалла это делается командой

$ make fetch-list

ответом на что будет нечто вроде:

/usr/bin/env /usr/bin/fetch -ARr -S 252636 \
ftp://ftp.rxvt.org/pub/rxvt/./rxvt-2.6.4.tar.bz2  || \
/usr/bin/env /usr/bin/fetch -ARr -S 252636  \
ftp://ftp.rxvt.org/pub/rxvt/old/rxvt-2.6.4.tar.bz2  ||\
/usr/bin/env /usr/bin/fetch -ARr -S 252636  \
ftp://ftp.rxvt.org/pub/rxvt/devel/rxvt-2.6.4.tar.bz2  ||\
... || \
echo rxvt-2.6.4.tar.bz2 not fetched

А для учета всех зависимостей существует особая цель -

$ make fetch-recursive-list

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

Следует только учесть, что при указании цели fetch в любых ее вариантах проверяется наличие соответствующих файлов исходников в каталоге /usr/ports/distfiles, поэтому любую из указанных команд нужно выполнять на машине, где их заведомо не имеется (или временно переименовывать каталог /usr/ports/distfiles). К сожалению, в системе портов FreeBSD не имеется аналога опций empty и empty-tree для emerge из портежей Gentoo, которые определяют зависимости при допущении, что база данных установленных пакетов пуста.

Любая уважающая себя система пакетного менеджмента должна обеспечивать не только инсталляцию оных, но и максимально чистое удаление установленного хозяйства. И система портов FreeBSD отвечает этому требованию в полной мере: для этого в ней предусмотрена цель deinstall. О цели clean я уже говорил. А еще есть более радикальная цель - distclean, очищающая не только рабочий каталог порта, но и каталог distfiles от скачанных для этого порта файлов.




Комментарии

Страницы комментариев: 1 :: 2 :: следующая

аноним, Fri Jul 10 00:01:50 2009:
Полезная статья. Но мне кажется тексту не хватает более четкого разграничения между понятиями пакета, его порта в системе и установленной программы. Хотя понимание этих различий навевает в процессе чтения.
Алексей Федорчук, Sat Nov 22 16:52:52 2008:
2 Chezare
make clean в корне дерева портов
Chezare, Fri Oct 24 17:50:58 2008:
>Если на стадии конфигурирования порта будет выявлено отсутствие в системе пакетов, с которыми он связан зависимостями, они будут автоматически скачаны и установлены...

Вот мучает меня вопрос: Если при построении конкретного пакета для очистки дерева исходников достаточно выполнить make clean, то как очистить деревья исходников пакетов-зависимостей? Неужели вручную из каждого каталога? о_О
Виктор, Thu Oct 2 18:25:38 2008:
очень хорошая и толковая статья, читал много книжек, но такой толковой статьи не видел. Спасибо!!!
victor, Wed Oct 1 04:06:28 2008:
Занимательная и интересная статья у вас. В отличие от большинства остальных похожих почти нет воды! :)
vle, Thu Sep 11 14:54:09 2008:
В dragonflybsd давно уже pkgsrc ;-)
Чего и всем BSD-шниками не только желаю ;-)
аноним, Tue Sep 9 21:22:20 2008:
Филлин, вторник, 9 сентября 2008 г. 06:37:56:
Мне вот интересно, а комментарии которые не нравятся автору здесь трут? :)

По БЗДе не трут. Плохие каменты могут появится только в больной голове. Это как раритет.
Алексей Федорчук, Tue Sep 9 10:47:00 2008:
2 Филлин
Еще как трут. Ваш оставлен только в назидание прочим :)
Филлин, Tue Sep 9 06:37:56 2008:
Мне вот интересно, а комментарии которые не нравятся автору здесь трут? :)
GeniusMaster, Thu Sep 4 08:22:23 2008:
Ага! Большое спасибо! Теперь на целую неделю есть работа! :)

Страницы комментариев: 1 :: 2 :: следующая

Комментарии заморожены.

Новости:

Все новости на CitCity.ru

Компании месяца

 
Последние комментарии
Почему школам следует использовать только свободные программы (101)
20 Декабрь, 14:51
ОСТОРОЖНО: ВИНДОФИЛИЯ! (2250)
http://komputernaya.ru/ - абонентское обслуживание компьютеров.
24 Декабрь, 22:53
Linux в школе: мифы про школу и информатику (334)
24 Декабрь, 22:43
Kubuntu Feisty (15)
24 Декабрь, 18:42
Software is like sex: it's better when it's free.
©Linus Torvalds