Spec

Материал из ALT Linux Wiki


Stub.png
Данная страница находится в разработке.
Эта страница ещё не закончена. Информация, представленная здесь, может оказаться неполной или неверной.


Работа с upstream-исходниками

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

%define origname imms

Name: xmms-%origname
#...

Url: http://www.luminal.org/phpwiki/index.php/IMMS
Source: http://www.luminal.org/files/%origname/%origname-%version.tar.bz2

# if we had a published package with original name
Obsoletes: %origname

%prep
%setup -n %origname-%version

Разумеется, это всё относится только к пакетам, собираемым не с помощью Gear.

Включение/выключение подпакетов

Иногда определённые подпакеты нужно собирать только в особых ситуациях (например, статические библиотеки или вариант для bootstrap новой архитектуры). Это делается следующим образом:

# По умолчанию будет выключено.
# Одноразово в командной строке rpm/rpmbuild включается с помощью --enable=static
%def_disable static
[...]
# Если заодно необходимо передавать опцию --(disable|enable)-static в configure,
# то можно написать следующую конструкцию.
# (В разных случаях она будет раскрываться в разные значения.)
%configure %{subst_enable static}
[...]
%if_enabled static
%files devel-static
[...]
%endif

Проверка плагинов

У нас в rpm-build >= 4.0.4-alt100.91 есть механизм проверки плагинов, который используется в разных пакетах. Вот, например, ldv когда-то применил его для irssi, выглядит это так (%_bindir/irssi можно прелоадить, потому что он PIE):

export RPM_LD_PRELOAD_irssi=%buildroot%_bindir/irssi
export RPM_FILES_TO_LD_PRELOAD_irssi='%irssi_modules_dir/lib*.so %perl_vendor_autolib/Irssi/*.so'
export RPM_LD_PRELOAD_libperl_core='%buildroot%irssi_modules_dir/libperl_core.so'
export RPM_FILES_TO_LD_PRELOAD_libperl_core='%irssi_modules_dir/libfe_perl.so %perl_vendor_autolib/Irssi/*.so'
%set_verify_elf_method strict

Version

Версия upstream-кода.

В случае упаковки промежуточной версии (1.0-rc1, 1.0-20080105) версия среза упаковывается в поле Release: 1.0rc лексикографически круче 1.0, вследствие чего для нормального обновления 1.0rc до 1.0 придётся

  • добавлять Serial: 1,
  • оформлять как 1.0rel или
  • ждать поднятия версии апстримом.

Чтобы избежать таких сложностей в случае, когда разработчик апстрима именует промежуточные версии без учёта лексикографического порядка сортировки, в номер версии в нужном месте добавляем свой суффикс «.0». Например, в случае планов апстрима после 1.0 выпустить 1.0.1, для промежуточной у апстрима версии 1.0.1-rc1 в спеке пишем 1.0.0.1-rc1.

Расшифровка именования промежуточных версий

На примере libxml2 2.9.4.0.12.e905-alt1:

  • у апстрима v2.9.4-12-ge905f08 — это вывод git describe e905f08;
  • «12» - это количество коммитов, отделяющих коммит «e905f08» от «v2.9.4»;
  • «.0» - это суффикс, добавленный к версии 2.9.4, чтобы получившийся результат 2.9.4.0 был гарантированно меньше любой версии, выпущенной после 2.9.4;
  • «e905» получен с помощью git describe --abbrev=1 e905f08;
  • «2.9.4.0.12.e905» написан по мотивам вывода утилиты git-version-gen из gnulib.

Release

Для пакетов Sisyphus поле Release должно иметь вид в простых случаях — altN, а в сложных (см. ниже) — altN[суффикс].

Релиз пакета используется для указания номера сборки пакета при данной версии upstream-кода, N начинается с 1 для каждой новой upstream-версии и увеличивается на 1 для каждой новой сборки:

  • 1.0-alt1
  • 1.0-alt2
  • 1.0-alt3
  • 1.1-alt1
  • 1.2-alt1
  • 1.2-alt2

Два особых случая — это упаковка промежуточных релизов upstream-кода и упаковка бэкпортов.

Промежуточные upstream-релизы

При сборке промежуточных релизов upstream-кода (срезов по дате, по системе контроля версий), следует указывать информацию о срезе в поле Release:

  • 1.0-alt1.r6543
  • 1.0-alt1.20080101
  • 1.0-alt1.rc1
  • 1.0-alt1.rc2
  • 1.0-alt1.gitda39a3ee[1]

Если система контроля версий не предоставляет линейной нумерации коммитов, то с каждым новым срезом нужно увеличивать номер релиза:

  • 1.0-alt1.hg.da39a3ee
  • 1.0-alt2.hg.0d3255bf
  • 1.0-alt3.hg.fef95601

При первой сборке финального upstream-релиза следует поднять номер релиза пакета:

  • 1.0-alt1.gitda39a3ee
  • 1.0-alt2.gitd06f1866
  • 1.0-alt3

Использовать релиз alt0 запрещено — пакет с таким релизом, попав в репозиторий, порождает проблемы с бэкпортами (в отличие от, например, alt0.1, который при бэкпорте для p7 становится alt0.0.M70P.1).

Бэкпорты


Epoch

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

Будьте осторожны — в имя RPM-файлов Epoch не входит, и поэтому необходимо избегать RPM-ов с одинаковыми Version и Release и разными Epoch.

Устаревшим синонимом поля Epoch является Serial.

Summary

Cодержит краткое описание пакета. Оно выводится, например, при поиске пакета через apt-cache search. Значение тэга Summary должно начинаться с заглавной буквы. В конце Summary не должно быть точки.

License

  • Лицензия должна быть указана в точности так, как сформулировано в upstream-пакете (в частности, не разрешается отбрасывать или добавлять «or any later version», а также менять указанные версии или смешивать GPL и LGPL).
  • Несвободные лицензии должны быть указаны как «distributable»

При указании лицензии рекомендуется пользоваться макросами из пакета rpm-build-licenses, добавив его в список BuildRequires.

Сам текст лицензии упаковывать в пакет нужно только в том случае, если соответствующий текст отсутствует в /usr/share/license (пакет common-licenses). Если же таковой файл там присутствует, то достаточно указать название лицензии в тэге пакета.

Лицензию с добавками к стандартному тексту (например, GPLv2 с дополнительной секцией в ядре Linux) упаковывать обязательно.

С ноября 2019 года в sisyphus_check в режиме предупреждения включена проверка на соответствие содержимого тега License: классификации SPDX (соответственно дополнено содержимое пакета common-licenses).

Список установленных из common-licenses можно увидеть с командой

ls -lp /usr/share/license

Group

Указанная группа должна находиться в списке групп, известном RPM. Этот список располагается в файле /usr/lib/rpm/GROUPS, находящемся в пакете rpm.

Url

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

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

Для тега Url можно использовать утилиту rpmurl из пакета etersoft-build-utils:

rpmurl -c пакет.spec

Source

Если сборка производится без использования gear, то в Source настоятельно рекомендуется указывать действующий URL архива исходного кода относительно тэга Url:

Source: %url/some/thing/%name-%version.tar.bz2

Формат Source для известных хостингов:

# иногда проект называется не так, как пакет, будьте внимательны
Source: http://dl.sourceforge.net/%name/%name-%version.tar.bz2
Source: http://download.berlios.de/%name/%name-%version.tar.bz2

Если тарбол формируется из gear-репозитория, то в Source указывается имя файла согласно прописанному в .gear/rules, например

Source: %name-%version.tar

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

# svn co svn://svnanon.samba.org/samba/trunk samba-trunk -r 1
Source: %name.tar.bz2


В некоторых случаях требуется использование нескольких файлов с исходниками. Так происходит, например, при использовании Gear/tags.

# Two different source files
 Source: %name.tar.bz2
 Source11: libfantastic.tar
# Later you would use 
# %setup -a11
# to install sources from libfantastic.tar

Patch

Рекомендуемое именование патчей:

  • NAME-VERSION-ORIGIN-WHAT.patch, где
    • NAME и VERSION — имя и версия пакета, для которого сделан патч,
    • ORIGIN — аббревиатура источников патча (обычно дистрибутивов),
    • WHAT — краткое описание патча.

Если патч образован из нескольких частей, полученных из разных источников, ORIGIN должен включать аббревиатуры всех источников. Аббревиатура ALT Linux / Sisyphus — alt. Для патчей, полученных на основе системы контроля версий, ORIGIN должен включать в себя дату или номер ревизии.

В описании патча рекомендуется пользоваться следующими сокращениями:

  • makefile — патчи, затрагивающие исключительно Makefile*,
  • bound — проверки на границы (буфера, целых чисел и т. д.),
  • config — патчи, затрагивающие исключительно конфигурационные файлы,
  • configure — патчи, затрагивающие исключительно configure*,
  • doc — патчи, затрагивающие исключительно документацию,
  • fixes — кумулятивные патчи/исправления по надёжности и/или безопасности,
  • format — патчи на использование форматирования строк (типа printf),
  • install — патчи на выполнение make install непривилегированным пользователем,
  • linux — патчи для портирования По на Linux,
  • man — патчи, затрагивающие исключительно man-страницы,
  • texinfo — патчи, затрагивающие исключительно документацию в формате texinfo,
  • tmp — патчи, предназначенные для решения различных вопросов, связанных с временными файлами,
  • vitmp — патчи для поддержки vitmp(1)
  • warnings — патчи, исправляющие предупреждения, выданные компилятором

(начиная с rpm-build 4.0.4-alt133) Все патчи, описанные в основной секции spec-файла, можно в секции %prep применить директивой %autopatch. %autopatch принимает опции -p и -F, аналогичные таким же опциям директивы %patch.

Requires

Используется для обозначения зависимостей между пакетами, которые необходимо удовлетворить для нормальной работы программ, не входящих в пакет с создаваемым/корректируемым спеком.

Requires:  java >= 1.6

При наличии логических зависимостей между пакетами внутри одного spec-файла, пакетная зависимость между ними должна включать полную версию пакета, например так:

Requires: %name = %epoch:%version-%release

Имеется короткая и удобная версия этой записи:

Requires: %name = %EVR


BuildRequires, BuildPreReq, BuildRequires(pre)

Тег BuildRequires используется для хранения результатов работы buildreq. По этой причине дополнительные сборочные зависимости, не находящиеся buildreq, рекомендуется хранить в теге BuildPreReq (устарело).

Если в пакете имеются опциональные части (включаемые с помощью конструкций %if или подобных), то сборочные зависимости должны содержать пакеты, достаточные для сборки всех опциональных частей. Этого можно добиться двумя способами:

  • запуском buildreq со всеми включенными опциями,
  • указанием дополнительных зависимостей в BuildPreReq и периодическим их обновлением.

При необходимости наличия в окружении, где выполняется раскрытие макросов для создания src.rpm, дополнительных пакетов rpm-macros-* либо rpm-build-* их следует указать тегом BuildRequires(pre). Злоупотреблять им не следует (затрудняет бутстрапы); критерий необходимости именно этой формы -- ошибка (не предупреждение!) при попытке выполнить в недостаточном окружении команду вида

rpm -bs --nodeps этот.spec

Обратите внимание, что для gear-rpm ограничения иные и этот критерий неприменим.

Тег BuildPreReq может использоваться для управления свойствами сборочного окружения, для этого в нём указываются зависимости на предопределённые имена, которые обрабатываются сборочной средой отдельно:

  • /proc — для монтирования в окружение виртуальной файловой системы proc (требуется, например, при сборке большинства пакетов на Java)
  • /dev/pts — для доступа из окружения к подсистеме псевдотерминалов ptmx (требуется, например, при тестировании некоторых утилит командной строки)
  • (to be continued…)

BuildArch

Используется для указания архитектуры (под)пакета. Возможные значения:

  • x86_64
  • %ix86[2] или индивидуально i386, i586, i686...
  • noarch

В случае указания среди тегов основного пакета определяет архитектуру всех подпакетов; для индивидуальных подпакетов — как правило, с данными, документацией либо скриптами — допускается указание только noarch, и то при условии использования rpm-4.0.4-alt94 или более новой сборки.

В данное время BuildArch используется в сочетании BuildArch noarch. Текущая практика предполагает сборку пакета под все доступные архитектуры, за исключением тех, под которые сборка не возможна. Обычно используется один из этих вариантов:

  • ExcludeArch: armh
  • ExcludeArch: ppc64le
  • ExcludeArch: %not_qt5_qtwebengine_arches


Либо для сборки под некоторые архитектуры вводятся дополнительные условия. Пример:

%ifarch %e2k ppc64le
%def_disable qtwebengine
%else
%def_enable qtwebengine
%endif

BuildRoot

Тэг BuildRoot бесполезен для RPM из Sisyphus: обработку BuildRoot RPM производит самостоятельно.

BuildHost

Новый опциональный тэг в Sisyphus RPM. Позволяет переопределить имя сборочного хоста. По умолчанию используется, как и в остальных версиях RPM, результат вызова uname(2).

Prefix

Тэг Prefix в Sisyphus RPM не нужен, он самостоятельно устанавливается в /usr.

Conflicts

Применяется для указания наличия конфликта (обязательно в случае файлового/RPC и желательно в случае существенного смыслового) между данным пакетом и указываемым. Не надо ставить конфликты на то, чего ещё нет и о чём, соответственно, ничего не известно. Достаточно проставить односторонне.

Provides

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

Provides: something = %version-%release

При переименовании пакета обязательно сочетается с Obsoletes:.

Obsoletes

Перечисляет пакеты/версии, объявленные устаревшими. Обычно применяется при переименовании пакета в сочетании с Provides: и с указанием версии, меньшей или равной последней известной версии пакета под старым названием:

Name: someproject
Version: 1.0
Release: alt1
# ...
Provides: oldproject = %version-%release
Obsoletes: oldproject <= 0.9.1

(Примечание: Реагирует ли сборочница на переименование пакетов.)

%description

Здесь указывается описание пакета. Данное описание учитывается при поиске пакета через apt-cache search и полностью выводится во время просмотра информации о пакете при помощи apt-cache show имя_пакета.

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

  • Описание программы или инструмента должно содержать их функционал, а не особенности реализации (язык, используемые библиотеки и т. д.)
  • Описание библиотеки должно содержать язык программирования, для которого предназначена библиотека, и решаемую задачу

Длина каждой строки не должна превышать 72 символа ради читабельности в различных случаях.

%prep

%setup

Макрос %setup распаковывает исходный код перед компиляцией.

Конструкция %setup в Sisyphus RPM использует флаг -q (quiet) по умолчанию. Для включения отладочного вывода используйте флаг -v.

Для тарболов с отличающимся от рекомендуемого GNU именованием содержимого (когда архив на верхнем уровне содержит лишь соответствующий каталог имя-версия), можно применять следующий вариант:

%setup -c
%setup -DTn %name-%version/%name

%build

%configure

Макрос используется для упрощения выполнения ./configure с соответствующими параметрами данной платформы. Почти всегда вполне достаточно выполнить %configure без параметров. От имени пользователя данный макрос работать не будет.

 %build
 %configure
 %make_build

При сборке пакетов проверяйте, нет ли в спеке --enable-strip. Обычно от него нет никакого эффекта, кроме убивания debuginfo на корню[3].

Если скрипта configure в архиве исходных текстов нет (обычное явление для исходников из git или иных SCM), но есть configure.ac -- следует добавить перед вызовом %configure макрос %autoreconf. В иных случаях стоит повнимательней ознакомиться с инструкциями по сборке, раз это не было сделано до сих пор.

%make_build

По умолчанию поддерживает при сборке использование нескольких процессоров/ядер.

%install

%makeinstall_std

Рекомендуемый вариант, эквивалентный

%make_install DESTDIR=%buildroot install

%make_install

Этот макрос используется для упрощения установки софта, Makefile которого умеет использовать параметр DESTDIR (в частности, весь софт, использующий automake, это умеет):

%make_install DESTDIR=%buildroot install

или

%make_install DESTDIR=%buildroot %_make_install_target

%makeinstall

Редко используемый макрос, предназначенный для софта, DESTDIR не умеющего, и prefix внутри себя не запоминающего:

%makeinstall

В случае, когда Makefile нужно передать какой-то дополнительный параметр (например, особо странный somefancydir=%buildroot/fancy/dir), это выглядит так:

%makeinstall somefancydir=%buildroot/fancy/dir

Иногда требуется запаковать вспомогательные бинарные программы, не предназначеные для выполнения пользователем (обычно их запускают другие программы). Согласно GNU Coding Standards, их следует класть в директорию, определяемую переменной libexecdir. В ALT Linux ей соответствует макрос %_libexecdir, указывающий на /usr/lib. Рекомендуется создавать в этой директории под-папки по названию пакета:

%makeinstall libexecdir=%buildroot%_libexecdir/fancy

Задать путь можно также на этапе конфигурирования:

%build
%configure --libexecdir=%_libexecdir/fancy

Удаление buildroot

В Sisyphus RPM buildroot удаляется самим RPM, и поэтому удалять его вручную не требуется.

%check

Начиная с rpm-4.0.4-alt98.18, для упрощения проведения автоматических тестов собранного кода поддерживается секция %check; типичные примеры её содержания:

  • если важно получить ответ на вопрос "не испортилось ли" поскорее, то
 %make_build check
  • если SMP-сборка не поддерживается, то
 make check
  • если важно узнать, какие именно тесты не прошли, то следует использовать ключ -k.

Обратите внимание: %check выполняется после %install, т.е. by design не влияет на результат работы %install.

Ненулевой код возврата по умолчанию приводит к останову сборки (в т.ч. и на girar); это возможно изменить при помощи ключей --disable check/--without check/--disable test/--without test или макроса

%def_disable check

Кроме того, отключение %check происходит при выполнении под управлением buildreq.

При необходимости вытащить для изучения и/или апстрима, например, testsuite.log применяется[4]:

make check || {
        find -type f -name testsuite.log -print0 | xargs -r0 cat
        exit 1
}

BuildRequires только для %check

Для возможности сборки с облегчёнными сборочными зависимостями (например, при bootstrap-е на новой платформе) желательно оформить BuildRequires только для %check как условные. Как следует из описания механизма выше, годится, например, такое выражение:

%{?!_without_test:%{?!_disable_test:%{?!_without_check:%{?!_disable_check:BuildRequires: fakechroot}}}}

но на практике (например, в спеке пакета rpm или в спеке пакета gcc7) часто встречается более короткое выражение:

%{?!_without_check:%{?!_disable_check:BuildRequires: fakechroot}}

(На свой страх можете ещё сократить это условие до %{?!_disable_check:BuildRequires: fakechroot}, но это может запутать людей, если они не будут знать, что этот спек требует использования именно опции --disable check, а не --without check, и привести для них к неожиданному поведению rpmbuild.)

Первое полное выражение по смыслу эквивалентно следующей конструкции с if, которое и работает на практике, наверное, так же:

%if_without test
%else
%if_disabled test
%else
%if_without check
%else
%if_disabled check
%else
BuildRequires: fakechroot
%endif
%endif
%endif
%endif

Последнее краткое выражение %{?!_disable_check:BuildRequires: fakechroot} по смыслу эквивалентно следующей конструкции с if:

%if_disabled check
%else
BuildRequires: fakechroot
%endif

Как работает %def_enable check и можно ли его использовать

Это по логике работы похоже на то, как работает %def_enable check — объявление специфичного для пакета переключателя check; логика работы такого объявления грубо говоря сводится по смыслу к:

%if_disabled check
%else
%global _enable_check SPECIAL_VALUE
%endif

Так что эффекта последнего краткого выражения %{?!_disable_check:BuildRequires: fakechroot} можно добиться ещё и, например, так — объявив специфичный для пакета переключатель check:

%def_enable check
...
%{?_enable_check:BuildRequires: fakechroot}

или

%def_enable check
...
%if_enabled check
BuildRequires: fakechroot
%endif

(Пример такого самого простого подхода с %def_enable check можно увидеть в спеке python3-module-oslotest.)

Удобство в том, что можно много раз в спеке (когда надо) просто проверять %if_enabled check (или %{?_enable_check:...}) по одному объявленному имени переключателя вместо четырёх возможных — при условии, что пишущий спек предварительно обобщил объявление своего переключателя check до:

%if_without test
%else
%if_disabled test
%else
%if_without check
%else
%def_enable check
%endif
%endif
%endif

На практике такое (в упрощённом виде) появилось в спеке apt[1]):

# Honor both kind of options: --{without,disable} check;
# and allow to simply write %%if_enabled check below.
%if_without check
%else
%def_enable check
%endif

...

# dependencies of tests
%if_enabled check
BuildRequires: /usr/bin/genbasedir
BuildRequires: gpg-keygen
BuildRequires: /usr/sbin/nginx
BuildRequires: /usr/bin/openssl
%endif

К сожалению, сделать такое расширенное объявление в системных макросах нельзя, потому что тогда не будет работать %def_disable check в спеках. (Можно было бы предложить добавить такой макрос %def_enable_check_unless_check_is_off, чтобы им пользовались авторы спеков, но его всё равно надо будет вручную вписывать в спек после места, где потенциально может быть написано %def_disable check и т.п. Или научить rpm-build понимать BuildRequires(check): ....)

checkinstall-подпакет как альтернатива %check

Основная статья: RPM/checkinstall


%clean

Sisyphus RPM автоматически очищает BuildRoot пакета (с помощью макроса %clean_buildroot). Таким образом, ручная очистка BuildRoot является ненужной (а точнее — вредной, поскольку повышает вероятность ошибки).

Если секция %clean пуста, то рекомендуется вообще не включать её в spec-файл.

%files

В отличие от других веток RPM, Sisyphus RPM автоматически подставляет в начало каждой секции %files и в начало каждого файла, включаемого с помощью %files -f, директиву %defattr со значением макроса %_defattr.

Таким образом, ручное указание %defattr является излишним.

%changelog


Примеры

Основная статья: Spec/sample


Ссылки

Примечания

  1. для ссылки на коммит удобен git describe
  2. См. rpm --eval %ix86
  3. http://lists.altlinux.org/pipermail/devel/2011-March/189039.html
  4. vsu@ в devel@