Spec: различия между версиями

Материал из ALT Linux Wiki
м (→‎%description: typo-)
 
(не показано 68 промежуточных версий 19 участников)
Строка 1: Строка 1:
[[Категория:RPM spec]]
[[Категория:RPM spec]]
[[Категория:Сборка_пакетов]]


{{Stub}}
{{Stub}}
== Что такое Spec-файл ==
Spec - это файл, описывающий пакет [[RPM]]. Он содержит инструкции по сборке пакета и метаданные, содержащие подробную информацию о нем. В spec-файле можно выделить разделы:
* в начале принято задавать переменные и управляющие директивы RPM, которые будут использоваться в дальнейшем (см. например разделы [[#Работа с upstream-исходниками]] и [[#Включение/выключение подпакетов]] ниже).
* затем идёт ''преамбула'' или ''заголовок'', в котором при помощи ''директив'' задаются метаданные пакета, такие как имя, версия, зависимости. Основные такие директивы описаны ниже.
* далее, идут разделы, описывающие различные этапы сборки пакета: [[#%prep|%prep]], [[#%build|%build]], [[#%install|%install]], [[#%check|%check]]
* далее, при необходимости [[#Предустановочные_и_постустановочные сценарии|предустановочные и постустановочные сценарии]] '''%pre''', '''%preun''', '''%post''' и '''%postun'''.
* далее, секция (или несколько) [[#%files|%files]], описывающаяя, какие файлы будут запакованы в пакет
* завершает spec [[#%changelog|%changelog]].


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


  # Включается с помощью --enable=static в командной строке rpm/rpmbuild.
  # По умолчанию будет выключено.
# Одноразово в командной строке rpm/rpmbuild включается с помощью --enable=static
  %def_disable static
  %def_disable static
  [...]
  [...]
  # Если необходимо передать опцию --(disable|enable)-static в configure
  # Если заодно необходимо передавать опцию --(disable|enable)-static в configure,
# то можно написать следующую конструкцию.
# (В разных случаях она будет раскрываться в разные значения.)
  %configure %{subst_enable static}
  %configure %{subst_enable static}
  [...]
  [...]
Строка 37: Строка 58:
  [...]
  [...]
  %endif
  %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 ==
== Version ==


Версия upstream-кода. В случае упаковки промежуточной версии ({{pkg|1.0-rc1}}, {{pkg|1.0-20080105}}) версия среза упаковывается в поле [[#Release|Release]]: 1.0rc [http://lists.altlinux.org/pipermail/devel/2007-September/144131.html лексикографически круче] 1.0, вследствие чего для нормального обновления 1.0rc до 1.0 придётся
Версия upstream-кода.
 
В случае упаковки промежуточной версии ({{pkg|1.0-rc1}}, {{pkg|1.0-20080105}}) версия среза упаковывается в поле [[#Release|Release]]: 1.0rc [http://lists.altlinux.org/pipermail/devel/2007-September/144131.html лексикографически круче] 1.0, вследствие чего для нормального обновления 1.0rc до 1.0 придётся
* добавлять <tt>Serial: 1</tt>,
* добавлять <tt>Serial: 1</tt>,
* оформлять как 1.0rel или
* оформлять как {{pkg|1.0rel}} или
* ждать поднятия версии апстримом.
* ждать поднятия версии апстримом.
Чтобы избежать таких сложностей в случае, когда разработчик апстрима именует промежуточные версии без учёта лексикографического порядка сортировки, в номер версии в нужном месте добавляем свой суффикс «.0». Например, в случае планов апстрима после {{pkg|1.0}} выпустить {{pkg|1.0.1}}, для промежуточной у апстрима версии {{pkg|1.0.1-rc1}} в спеке пишем {{pkg|1.0.0.1-rc1}}.
==== Расшифровка именования промежуточных версий ====
На [https://lists.altlinux.org/pipermail/devel/2019-May/207886.html примере] {{pkg|libxml2 2.9.4.0.12.e905-alt1}}:
* у апстрима {{pkg|v2.9.4-12-ge905f08}} — это вывод <code>git describe e905f08</code>;
* «12» - это количество коммитов, отделяющих коммит «e905f08» от «v2.9.4»;
* «.0» - это суффикс, добавленный к версии {{pkg|2.9.4}}, чтобы получившийся результат {{pkg|2.9.4.0}} был гарантированно меньше любой версии, выпущенной после {{pkg|2.9.4}};
* «e905» получен с помощью <code>git describe --abbrev=1 e905f08</code>;
* «2.9.4.0.12.e905» написан по мотивам вывода утилиты <code>git-version-gen</code> из <code>gnulib</code>.


== Release ==
== Release ==
Строка 71: Строка 115:
* {{pkg|1.0-alt1.rc2}}
* {{pkg|1.0-alt1.rc2}}
* {{pkg|1.0-alt1.gitda39a3ee}}
* {{pkg|1.0-alt1.gitda39a3ee}}
* {{pkg|1.0-alt1.10.gda39a3e}}<ref>Для ссылки на коммит удобен {{cmd|git describe --tags}}, который в апстримной ветке с тэгами возвращает примерно такую информацию: "1.0-10-gda39a3e", где 1.0 - это версия, 10 - это количество коммитов после тэга, da39a3e - это его хэш.</ref>
Или же в поле {{term|Version}}:
* {{pkg|1.0.10.gda39a3e-alt1}}<ref>Такой подход предложил glebfm [https://bugzilla.altlinux.org/show_bug.cgi?id=40302#c18 в этом баге].</ref>


Если система контроля версий не предоставляет линейной нумерации коммитов, то с каждым новым срезом нужно увеличивать номер релиза:
Если система контроля версий не предоставляет линейной нумерации коммитов, то с каждым новым срезом нужно увеличивать номер релиза:
Строка 77: Строка 125:
* {{pkg|1.0-alt2.hg.0d3255bf}}
* {{pkg|1.0-alt2.hg.0d3255bf}}
* {{pkg|1.0-alt3.hg.fef95601}}
* {{pkg|1.0-alt3.hg.fef95601}}
Для линеаризации номера версии в {{pkg|git}} можно использовать {{cmd|git describe}}:
* {{pkg|1.0-alt1.git1.5.4-1-g18208b2}}
* {{pkg|1.0-alt1.git1.5.4-2-93f1595a}}
* {{pkg|1.0-alt1.git1.5.4-3-8be800af}}
:Но похоже такие релизы не работают на [[git.alt]]:
error: line 8: Illegal char '-' in release: Release: alt1.git1.2.1-84-g8fa890f


При первой сборке финального upstream-релиза следует поднять номер релиза пакета:
При первой сборке финального upstream-релиза следует поднять номер релиза пакета:
Строка 93: Строка 132:
* {{pkg|1.0-alt3}}
* {{pkg|1.0-alt3}}


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


=== Бэкпорты ===
=== Бэкпорты ===
Строка 116: Строка 155:
* Несвободные лицензии должны быть указаны как «distributable»
* Несвободные лицензии должны быть указаны как «distributable»


При указании лицензии рекомендуется пользоваться макросами из пакета <tt>rpm-build-licenses</tt>.
При указании лицензии рекомендуется пользоваться макросами из пакета {{pkg|rpm-build-licenses}}, добавив его в список BuildRequires.


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


Лицензию с добавками к стандартному тексту (например, GPLv2 с дополнительной секцией в ядре Linux) упаковывать обязательно.
Лицензию с добавками к стандартному тексту (например, GPLv2 с дополнительной секцией в ядре Linux) упаковывать обязательно.
С ноября 2019 года в {{pkg|sisyphus_check}} в режиме предупреждения [https://lists.altlinux.org/pipermail/devel/2019-November/209050.html включена] проверка на соответствие содержимого тега <tt>License:</tt> классификации SPDX (соответственно дополнено содержимое пакета {{pkg|common-licenses}}).
Список установленных из {{pkg|common-licenses}} можно увидеть с командой <pre>ls -lp /usr/share/license</pre>


== Group ==
== Group ==
Строка 131: Строка 174:


Рекомендуется периодически проверять адреса в своих пакетах на предмет того, что они действующие, и проект не переехал (даже если по старому адресу стоит перенаправление на новый, имеет смысл исправить содержимое тэга).
Рекомендуется периодически проверять адреса в своих пакетах на предмет того, что они действующие, и проект не переехал (даже если по старому адресу стоит перенаправление на новый, имеет смысл исправить содержимое тэга).
Старайтесь не использовать макросы в этом теге. Это затрудняет доступ к ссылкам при работе со spec файлами. Подробнее в рассылке devel: [https://lists.altlinux.org/pipermail/devel/2024-February/218426.html Излишнее увлечение макросом %name в спеке].


Для тега <tt>Url</tt> можно использовать утилиту <tt>rpmurl</tt> из пакета <tt>etersoft-build-utils</tt>:
Для тега <tt>Url</tt> можно использовать утилиту <tt>rpmurl</tt> из пакета <tt>etersoft-build-utils</tt>:
  rpmurl -c пакет.spec
  rpmurl -c пакет.spec
== Vcs ==
{{term|VCS}} (Version Control System) — система контроля версий. В этом теге указывается ссылка на git репозиторий или на любую другую систему контроля версий.
Как и в {{term|Url}}, в этом теге следует избегать использования макросов, чтобы не затруднять доступ к ссылке при работе со spec файлами. Подробнее в рассылке devel: [https://lists.altlinux.org/pipermail/devel/2024-February/218426.html Излишнее увлечение макросом %name в спеке].
=== Совпадение значений тегов {{term|Url}} и {{term|Vcs}} ===
В случае, если проект не имеет отдельной страницы с информацией о нём, а лишь git репозиторий, например, на github, то не стесняйтесь указывать ссылку на него и в {{term|Url}}, и в {{term|Vcs}}. С точки зрения пользователя это дублирование информации, но с точки зрения сервисов, которые используют эти теги, это совсем не так. {{term|Url}} и {{term|Vcs}} это разные объекты, даже совпадение которых даёт какую-то информацию о проекте.


== Source ==
== Source ==
Строка 150: Строка 205:
  # svn co svn://svnanon.samba.org/samba/trunk samba-trunk -r 1
  # svn co svn://svnanon.samba.org/samba/trunk samba-trunk -r 1
  Source: %name.tar.bz2
  Source: %name.tar.bz2
В некоторых случаях требуется использование нескольких файлов с исходниками. Так происходит, например, при использовании [[Gear/tags]].
<syntaxhighlight lang="ini">
# Two different source files
Source: %name.tar.bz2
Source11: libfantastic.tar
# Later you would use
# %setup -a11
# to install sources from libfantastic.tar
</syntaxhighlight>


== Patch ==
== Patch ==
Строка 177: Строка 244:
* {{term|warnings}} — патчи, исправляющие предупреждения, выданные компилятором
* {{term|warnings}} — патчи, исправляющие предупреждения, выданные компилятором


== Requires, PreReq ==
<small>(начиная с rpm-build 4.0.4-alt133)</small> Все патчи, описанные в основной секции spec-файла, можно в секции [[#%prep|%prep]] применить директивой %autopatch. %autopatch принимает опции -p и -F, аналогичные таким же опциям директивы %patch.
 
== Requires ==
 
Используется для обозначения зависимостей между пакетами, которые необходимо удовлетворить для нормальной работы программ, не входящих в пакет с создаваемым/корректируемым спеком.
Requires:  java >= 1.6


При наличии логических зависимостей между пакетами внутри одного spec-файла, пакетная зависимость между ними должна включать полную версию пакета, например так:
При наличии логических зависимостей между пакетами внутри одного spec-файла, пакетная зависимость между ними должна включать полную версию пакета, например так:
  Requires: %name = %epoch:%version-%release
  Requires: %name = %epoch:%version-%release
Имеется короткая и удобная версия этой записи:
Requires: %name = %EVR


=== Requires ===


Используется для обозначения зависимостей между пакетами, которые необходимо удовлетворить для нормальной работы программ, выходящих в пакет.
== BuildRequires, BuildPreReq, BuildRequires(pre) ==
Requires: java >= 1.6
 
Теги <tt>BuildRequires</tt>, <tt>BuildPreReq</tt>, <tt>BuildRequires(pre)</tt> используются для указания сборочных зависимостей, то есть пакетов, которые должны быть установлены в текущее окружение при сборке.
 
Эти теги также могут использоваться для управления свойствами сборочного окружения. Для этого указываются зависимости на предопределённые имена, которые обрабатываются [[hasher|сборочной средой]] отдельно:
* {{path|/proc}} — для монтирования в окружение виртуальной файловой системы [https://man7.org/linux/man-pages/man5/proc.5.html proc] (требуется, например, при сборке большинства пакетов на Java)
* {{path|/dev/pts}} — для доступа из окружения к подсистеме псевдотерминалов [https://man7.org/linux/man-pages/man4/pts.4.html ptmx] (требуется, например, при тестировании некоторых утилит командной строки)
* (''to be continued…'')


== BuildRequires, BuildPreReq ==
=== buildreq ===


Тэг <tt>BuildRequires</tt> используется для хранения результатов работы [[buildreq]]. По этой причине дополнительные сборочные зависимости, не находящиеся <tt>buildreq</tt>, рекомендуется хранить в тэге <tt>BuildPreReq</tt>.
При использовании утилиты [[buildreq]] значения тегов <tt>BuildRequires</tt> автоматически и полностью заменяются результатами её работы. По этой причине дополнительные сборочные зависимости, не находящиеся <tt>buildreq</tt>, рекомендуется хранить в теге <tt>BuildPreReq</tt>.


Если в пакете имеются опциональные части (включаемые с помощью конструкций <tt>%if</tt> или подобных), то сборочные зависимости должны содержать пакеты, достаточные для сборки всех опциональных частей. Этого можно добиться двумя способами:
Если в пакете имеются опциональные части (включаемые с помощью конструкций <tt>%if</tt> или подобных), то сборочные зависимости должны содержать пакеты, достаточные для сборки всех опциональных частей. Этого можно добиться двумя способами:
* запуском <tt>buildreq</tt> со всеми включенными опциями,
* запуском <tt>buildreq</tt> со всеми включенными опциями,
* указанием дополнительных зависимостей в <tt>BuildPreReq</tt> и периодическим их обновлением.
* указанием дополнительных зависимостей в <tt>BuildPreReq</tt> и периодическим их обновлением.
=== BuildRequires(pre) ===
Зачастую для корректной интерпретации spec-файла необходимо наличие в окружении дополнительных пакетов -- например, пакетов в {{pkg|rpm-macros-*}} либо {{pkg|rpm-build-*}}, в которых определены используемые в spec-файле макросы. Такие пакеты следует указывать в теге <tt>BuildRequires(pre)</tt>.
При сборке через [[Gear]] (<tt>gear-hsh</tt> или <tt>gear --hasher</tt>) [[hasher]] обрабатывает теги <tt>BuildRequires(pre)</tt> особым образом: указанные в них пакты используются для построения первоначального сборочного окружения, в котором уже будут вычислены полные сборочные зависимости пакета. Эта обработка накладывает на тег  <tt>BuildRequires(pre)</tt> дополнительные ограничения:
* директива должна начинаться с начала строки (например, конструкции вида <tt>%{?_with_...:BuildRequires(pre): ...}</tt> игнорируются на этом этапе);
* условные конструкции (<tt>%if</tt>, <tt>%if_with</tt>, ...) также на этом этапе игнорируются; будут обработаны все <tt>BuildRequires(pre)</tt>, присутствующие в спеке;
* зависимости, в которых оказался символ <tt>%</tt>, также игнорируются, так что в тегах <tt>BuildRequires(pre)</tt> нельзя использовать макросы RPM ([[Gear/specsubst|specsubst]] использовать можно, он обрабатывается на более раннем этапе).
При сборке без gear -- через SRPM -- эти требования не предъявляются, однако им всё-таки рекомендуется следовать. Здесь разница pre/не-pre носит скорее характер документации; критерий необходимости именно формы с <tt>(pre)</tt> -- ошибка (не предупреждение!) при попытке выполнить в недостаточном окружении команду вида
rpm -bs --nodeps этот.spec


== BuildArch ==
== BuildArch ==
Строка 201: Строка 294:
* <tt>noarch</tt>
* <tt>noarch</tt>
В случае указания среди тегов основного пакета определяет архитектуру всех подпакетов; для индивидуальных подпакетов — как правило, с данными, документацией либо скриптами — допускается указание только <tt>noarch</tt>, и то при условии использования {{pkg|rpm-4.0.4-alt94}} или более новой сборки.
В случае указания среди тегов основного пакета определяет архитектуру всех подпакетов; для индивидуальных подпакетов — как правило, с данными, документацией либо скриптами — допускается указание только <tt>noarch</tt>, и то при условии использования {{pkg|rpm-4.0.4-alt94}} или более новой сборки.
В данное время BuildArch используется только в сочетании <tt>BuildArch noarch.</tt>
Текущая практика предполагает сборку пакета под все доступные архитектуры, за исключением тех, под которые сборка не возможна.
Обычно используется один из этих вариантов:
* ExcludeArch: armh
* ExcludeArch: ppc64le
* ExcludeArch: %not_qt5_qtwebengine_arches
Либо для сборки под некоторые архитектуры вводятся дополнительные условия. Пример:
<syntaxhighlight lang="ini">
%ifarch %e2k ppc64le
%def_disable qtwebengine
%else
%def_enable qtwebengine
%endif
</syntaxhighlight>


== BuildRoot ==
== BuildRoot ==
Строка 235: Строка 346:
  Provides: oldproject = %version-%release
  Provides: oldproject = %version-%release
  Obsoletes: oldproject <= 0.9.1
  Obsoletes: oldproject <= 0.9.1
(Примечание: [[Реагирует ли сборочница на переименование пакетов]].)


== %description ==
== %description ==


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


Описание пакета должно содержать информацию, интересную его пользователю, а не сборщику:
Описание пакета должно содержать информацию, интересную его пользователю, а не сборщику:
Строка 253: Строка 366:
Макрос %setup распаковывает исходный код перед компиляцией.
Макрос %setup распаковывает исходный код перед компиляцией.


Конструкция <tt>%setup</tt> в Sisyphus RPM использует флаг <tt>-q</tt> (quiet) по умолчанию. Для включения отладочного вывода используйте флаг <tt>-v</tt>.
Конструкция <tt>%setup</tt> в Sisyphus RPM использует флаг <tt>-q</tt> (quiet) по умолчанию.
 
Для тарболов с отличающимся от рекомендуемого GNU именованием содержимого (когда архив на верхнем уровне содержит лишь соответствующий каталог <tt>имя-версия</tt>), можно применять [https://bugzilla.altlinux.org/show_bug.cgi?id=31778#c7 следующий вариант]:
 
%setup -c
%setup -DTn %name-%version/%name


== %build ==
== %build ==
=== %configure ===
=== %configure ===
Макрос используется для упрощения выполнения ./configure с соответствующими параметрами данной платформы.
Макрос используется для упрощения выполнения {{path|./configure}} с соответствующими параметрами данной платформы.
Почти всегда вполне достаточно выполнить %configure без параметров.
Почти всегда вполне достаточно выполнить <tt>%configure</tt> без параметров.
От имени пользователя данный макрос работать не будет.
От имени пользователя данный макрос работать не будет.
   %build
   %build
Строка 265: Строка 383:


При сборке пакетов проверяйте, нет ли в спеке <tt>--enable-strip</tt>.  Обычно от него нет никакого эффекта, кроме убивания debuginfo на корню<ref>http://lists.altlinux.org/pipermail/devel/2011-March/189039.html</ref>.
При сборке пакетов проверяйте, нет ли в спеке <tt>--enable-strip</tt>.  Обычно от него нет никакого эффекта, кроме убивания debuginfo на корню<ref>http://lists.altlinux.org/pipermail/devel/2011-March/189039.html</ref>.
Если скрипта {{path|configure}} в архиве исходных текстов нет (обычное явление для исходников из git или иных SCM), но есть {{path|configure.ac}} -- следует добавить перед вызовом <tt>%configure</tt> макрос <tt>%autoreconf</tt>.  В иных случаях стоит повнимательней ознакомиться с инструкциями по сборке, раз это не было сделано до сих пор.


=== %make_build ===
=== %make_build ===
Строка 317: Строка 437:
[http://lists.altlinux.org/pipermail/devel/2009-September/174904.html Обратите внимание:] <tt>%check</tt> выполняется после <tt>%install</tt>, т.е. by design не влияет на результат работы <tt>%install</tt>.
[http://lists.altlinux.org/pipermail/devel/2009-September/174904.html Обратите внимание:] <tt>%check</tt> выполняется после <tt>%install</tt>, т.е. by design не влияет на результат работы <tt>%install</tt>.


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


  %def_disable check
  %def_disable check
Строка 328: Строка 448:
         exit 1
         exit 1
}</pre>
}</pre>
=== BuildRequires только для %check ===
Для возможности сборки с облегчёнными сборочными зависимостями (например, при bootstrap-е на новой платформе) желательно оформить BuildRequires только для %check как условные. Как следует из описания механизма выше, годится, например, такое выражение:
%{?!_without_test:%{?!_disable_test:%{?!_without_check:%{?!_disable_check:BuildRequires: fakechroot}}}}
но на практике (например, в [http://git.altlinux.org/gears/r/rpm.git?p=rpm.git;a=blob;f=alt/rpm.spec;h=c31235ba8911c234273874c7a05222e0679b01d2;hb=HEAD#l98 спеке пакета {{pkg|rpm}}] или в [http://git.altlinux.org/gears/g/gcc7.git?p=gcc7.git;a=blob;f=gcc.spec;h=e35394d0839e7f91722791bd28848891744e36c4;hb=cb37543edf6d176652517531af8c33ab1138ab0c#l219 спеке пакета {{pkg|gcc7}}]) часто встречается более короткое выражение:
%{?!_without_check:%{?!_disable_check:BuildRequires: fakechroot}}
(На свой страх можете ещё сократить это условие до <code>%{?!_disable_check:BuildRequires: fakechroot}</code>, но это может запутать людей, если они не будут знать, что этот спек требует использования именно опции {{cmd|--disable check}}, а не {{cmd|--without check}}, и привести для них к неожиданному поведению {{cmd|rpmbuild}}.)
Первое полное выражение по смыслу эквивалентно следующей конструкции с <code>if</code>, которое и работает на практике, наверное, так же:
%if_without test
%else
%if_disabled test
%else
%if_without check
%else
%if_disabled check
%else
BuildRequires: fakechroot
%endif
%endif
%endif
%endif
Последнее краткое выражение <code>%{?!_disable_check:BuildRequires: fakechroot}</code> по смыслу эквивалентно следующей конструкции с <code>if</code>:
%if_disabled check
%else
BuildRequires: fakechroot
%endif
====Как работает %def_enable check и можно ли его использовать====
Это по логике работы похоже на то, как работает <code>%def_enable check</code> — объявление специфичного для пакета переключателя <code>check</code>; логика работы такого объявления [http://git.altlinux.org/gears/r/rpm.git?p=rpm.git;a=blob;f=platform.in#l611 грубо говоря сводится по смыслу] к:
%if_disabled check
%else
%global _enable_check SPECIAL_VALUE
%endif
Так что эффекта последнего краткого выражения <code>%{?!_disable_check:BuildRequires: fakechroot}</code> можно добиться ещё и, например, так — объявив специфичный для пакета переключатель <code>check</code>:
%def_enable check
...
%{?_enable_check:BuildRequires: fakechroot}
или
%def_enable check
...
%if_enabled check
BuildRequires: fakechroot
%endif
(Пример такого самого простого подхода с <code>%def_enable check</code> можно увидеть в [http://git.altlinux.org/srpms/p/python3-module-oslotest.git?p=python3-module-oslotest.git;a=blob;f=oslotest.spec;h=5144960ed30e221dcada2a5d63419b12055d7544;hb=HEAD#l23 спеке {{pkg|python3-module-oslotest}}].)
Удобство в том, что можно много раз в спеке (когда надо) просто проверять <code>%if_enabled check</code> (или <code>%{?_enable_check:...}</code>) по одному объявленному имени переключателя вместо четырёх возможных — при условии, что пишущий спек предварительно обобщил объявление своего переключателя <code>check</code> до:
%if_without test
%else
%if_disabled test
%else
%if_without check
%else
%def_enable check
%endif
%endif
%endif
На практике такое (в упрощённом виде) появилось в [http://git.altlinux.org/gears/a/apt.git?p=apt.git;a=blob;f=apt.spec;h=deee52a230ff829eccb4b459d1b5f8a6828cf994;hb=HEAD#l1 спеке {{pkg|apt}}] (и [http://git.altlinux.org/gears/a/apt.git?p=apt.git;a=blob;f=apt.spec;h=deee52a230ff829eccb4b459d1b5f8a6828cf994;hb=HEAD#l87]):
# 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
К сожалению, сделать такое расширенное объявление в системных макросах нельзя, потому что тогда не будет работать <code>%def_disable check</code> в спеках. (Можно было бы предложить добавить такой макрос <code>%def_enable_check_unless_check_is_off</code>, чтобы им пользовались авторы спеков, но его всё равно надо будет вручную вписывать в спек после места, где потенциально может быть написано <code>%def_disable check</code> и т.п. Или научить {{pkg|rpm-build}} понимать <code>BuildRequires(check): ...</code>.)
====checkinstall-подпакет как альтернатива %check====
{{Main|RPM/checkinstall}}


== %clean ==
== %clean ==
Строка 334: Строка 550:


Если секция <tt>%clean</tt> пуста, то рекомендуется вообще не включать её в spec-файл.
Если секция <tt>%clean</tt> пуста, то рекомендуется вообще не включать её в spec-файл.
== Предустановочные и постустановочные сценарии ==
Механизмы RPM позволяют исполнить вспомогательные инструкции которые исполняются в различных случаях взаимодействия с rpm-пакетом. Эти инструкции содержатся в spec-файле и позволяют мэйнтейнеру дистрибутива подготовить предустановочные и постустановочные сценарии.
Сценарии иключают интерактивный режим и предполагают исполнение команд интерпретатора командной с правами супер пользователя.
Сценарий:
* %pre --- выполняется ''перед'' установкой пакета в систему.
* %post --- выполняется ''после'' установки пакета в систему.
* %preun --- выполняется ''перед'' удалением пакета из системы.
* %postun --- выполняется ''после'' удаления пакета из системы.
=== Проверка наличия пакета в системе ===
pre и post сценарии исполняются как при установке/удалении, так и при обновлении пакета в системе.
Специфика обновления пакета заключается в последовательном исполнении скриптов %pre, %post - нового пакета, и последующего исполнения %preun, %postun - старого пакета. Следовательно, в случае обновления сценарии %preun и %postun могут повлиять на %pre и %post сценарии.
Для управления подобными ситуациями предусмотрен специальный аргумент, который содержит количество экземпляров данного пакета в системе.
{| border="0"
|+ align="top" style="font-weight: bold;" | Значение $1, передаваемого сценариям pre и post:
! style="background:#f8f9fa; padding-inline:35px" | Значение \ Сценарий
! style="background:#f8f9fa; padding-inline:35px" | %pre
! style="background:#f8f9fa; padding-inline:35px" | %post
! style="background:#f8f9fa; padding-inline:35px" | %preun
! style="background:#f8f9fa; padding-inline:35px" | %postun
|- style="text-align: center;"
| первоначальная установка || 1 || 1 || Недоступно || Недоступно
|- style="text-align: center;"
| обновление || 2 || 2 || 1 || 1
|- style="text-align: center;"
| удаление || Недоступно || Недоступно || 0 || 0
|}
Пример проверки состояния пакета в системе:
%postun
if [ $1 -eq 0 ]; then
    echo "Выполнение сценария в случае удаления пакета"
fi
if [ $1 -eq 1 ]; then
    echo "Выполнение сценария в случае обновления пакета"
fi


== %files ==
== %files ==
Строка 344: Строка 604:


{{Main|Руководство по написанию changelog}}
{{Main|Руководство по написанию changelog}}
== Примеры ==
{{Main|Spec/sample}}
== Ссылки ==
* [http://docs.altlinux.org/archive/2.2/master/devel-html/ch01s02.html ALT specfile conventions]
* [[Spec/Предопределенные макросы]]
* [[Особенности написания спек файлов в ALT Linux]]
* [[SampleSpecs]]
* [[Knobs]]


== Примечания ==
== Примечания ==
<references />
<references />

Текущая версия от 08:46, 22 ноября 2024


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


Что такое Spec-файл

Spec - это файл, описывающий пакет RPM. Он содержит инструкции по сборке пакета и метаданные, содержащие подробную информацию о нем. В spec-файле можно выделить разделы:

  • затем идёт преамбула или заголовок, в котором при помощи директив задаются метаданные пакета, такие как имя, версия, зависимости. Основные такие директивы описаны ниже.
  • далее, идут разделы, описывающие различные этапы сборки пакета: %prep, %build, %install, %check
  • далее, секция (или несколько) %files, описывающаяя, какие файлы будут запакованы в пакет

Работа с 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.0-alt1.10.gda39a3e[1]

Или же в поле Version:

  • 1.0.10.gda39a3e-alt1[2]

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

  • 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 домашней страницы проекта, либо если таковой нет — любого другого места, где можно получить архив с исходным кодом.

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

Старайтесь не использовать макросы в этом теге. Это затрудняет доступ к ссылкам при работе со spec файлами. Подробнее в рассылке devel: Излишнее увлечение макросом %name в спеке.

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

rpmurl -c пакет.spec

Vcs

VCS (Version Control System) — система контроля версий. В этом теге указывается ссылка на git репозиторий или на любую другую систему контроля версий.

Как и в Url, в этом теге следует избегать использования макросов, чтобы не затруднять доступ к ссылке при работе со spec файлами. Подробнее в рассылке devel: Излишнее увлечение макросом %name в спеке.

Совпадение значений тегов Url и Vcs

В случае, если проект не имеет отдельной страницы с информацией о нём, а лишь git репозиторий, например, на github, то не стесняйтесь указывать ссылку на него и в Url, и в Vcs. С точки зрения пользователя это дублирование информации, но с точки зрения сервисов, которые используют эти теги, это совсем не так. Url и Vcs это разные объекты, даже совпадение которых даёт какую-то информацию о проекте.

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, BuildPreReq, BuildRequires(pre) используются для указания сборочных зависимостей, то есть пакетов, которые должны быть установлены в текущее окружение при сборке.

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

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

buildreq

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

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

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

BuildRequires(pre)

Зачастую для корректной интерпретации spec-файла необходимо наличие в окружении дополнительных пакетов -- например, пакетов в rpm-macros-* либо rpm-build-*, в которых определены используемые в spec-файле макросы. Такие пакеты следует указывать в теге BuildRequires(pre).

При сборке через Gear (gear-hsh или gear --hasher) hasher обрабатывает теги BuildRequires(pre) особым образом: указанные в них пакты используются для построения первоначального сборочного окружения, в котором уже будут вычислены полные сборочные зависимости пакета. Эта обработка накладывает на тег BuildRequires(pre) дополнительные ограничения:

  • директива должна начинаться с начала строки (например, конструкции вида %{?_with_...:BuildRequires(pre): ...} игнорируются на этом этапе);
  • условные конструкции (%if, %if_with, ...) также на этом этапе игнорируются; будут обработаны все BuildRequires(pre), присутствующие в спеке;
  • зависимости, в которых оказался символ %, также игнорируются, так что в тегах BuildRequires(pre) нельзя использовать макросы RPM (specsubst использовать можно, он обрабатывается на более раннем этапе).

При сборке без gear -- через SRPM -- эти требования не предъявляются, однако им всё-таки рекомендуется следовать. Здесь разница pre/не-pre носит скорее характер документации; критерий необходимости именно формы с (pre) -- ошибка (не предупреждение!) при попытке выполнить в недостаточном окружении команду вида

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

BuildArch

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

  • x86_64
  • %ix86[3] или индивидуально 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) по умолчанию.

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

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

%build

%configure

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

 %build
 %configure
 %make_build

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

Если скрипта 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 применяется[5]:

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-файл.

Предустановочные и постустановочные сценарии

Механизмы RPM позволяют исполнить вспомогательные инструкции которые исполняются в различных случаях взаимодействия с rpm-пакетом. Эти инструкции содержатся в spec-файле и позволяют мэйнтейнеру дистрибутива подготовить предустановочные и постустановочные сценарии.

Сценарии иключают интерактивный режим и предполагают исполнение команд интерпретатора командной с правами супер пользователя.

Сценарий:

  • %pre --- выполняется перед установкой пакета в систему.
  • %post --- выполняется после установки пакета в систему.
  • %preun --- выполняется перед удалением пакета из системы.
  • %postun --- выполняется после удаления пакета из системы.

Проверка наличия пакета в системе

pre и post сценарии исполняются как при установке/удалении, так и при обновлении пакета в системе.

Специфика обновления пакета заключается в последовательном исполнении скриптов %pre, %post - нового пакета, и последующего исполнения %preun, %postun - старого пакета. Следовательно, в случае обновления сценарии %preun и %postun могут повлиять на %pre и %post сценарии. Для управления подобными ситуациями предусмотрен специальный аргумент, который содержит количество экземпляров данного пакета в системе.

Значение $1, передаваемого сценариям pre и post:
Значение \ Сценарий %pre %post %preun %postun
первоначальная установка 1 1 Недоступно Недоступно
обновление 2 2 1 1
удаление Недоступно Недоступно 0 0

Пример проверки состояния пакета в системе:

%postun
if [ $1 -eq 0 ]; then
   echo "Выполнение сценария в случае удаления пакета"
fi
if [ $1 -eq 1 ]; then
   echo "Выполнение сценария в случае обновления пакета"
fi

%files

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

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

%changelog


Примеры

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


Ссылки

Примечания

  1. Для ссылки на коммит удобен git describe --tags, который в апстримной ветке с тэгами возвращает примерно такую информацию: "1.0-10-gda39a3e", где 1.0 - это версия, 10 - это количество коммитов после тэга, da39a3e - это его хэш.
  2. Такой подход предложил glebfm в этом баге.
  3. См. rpm --eval %ix86
  4. http://lists.altlinux.org/pipermail/devel/2011-March/189039.html
  5. vsu@ в devel@