Spec: различия между версиями
м (→Промежуточные upstream-релизы: ...нет, нельзя, поэтому и писать ни к чему) |
|||
(не показаны 63 промежуточные версии 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 новой архитектуры). Это делается следующим образом: | ||
# | # По умолчанию будет выключено. | ||
# Одноразово в командной строке rpm/rpmbuild включается с помощью --enable=static | |||
%def_disable static | %def_disable static | ||
[...] | [...] | ||
# Если необходимо | # Если заодно необходимо передавать опцию --(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 == | ||
Строка 70: | Строка 114: | ||
* {{pkg|1.0-alt1.rc1}} | * {{pkg|1.0-alt1.rc1}} | ||
* {{pkg|1.0-alt1.rc2}} | * {{pkg|1.0-alt1.rc2}} | ||
* {{pkg|1.0-alt1.gitda39a3ee}}<ref> | * {{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> | |||
Если система контроля версий не предоставляет линейной нумерации коммитов, то с каждым новым срезом нужно увеличивать номер релиза: | Если система контроля версий не предоставляет линейной нумерации коммитов, то с каждым новым срезом нужно увеличивать номер релиза: | ||
Строка 107: | Строка 155: | ||
* Несвободные лицензии должны быть указаны как «distributable» | * Несвободные лицензии должны быть указаны как «distributable» | ||
При указании лицензии рекомендуется пользоваться макросами из пакета | При указании лицензии рекомендуется пользоваться макросами из пакета {{pkg|rpm-build-licenses}}, добавив его в список BuildRequires. | ||
Сам текст лицензии упаковывать в пакет нужно только в том случае, если соответствующий текст отсутствует в <tt>/usr/share/license</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 == | ||
Строка 122: | Строка 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 == | ||
Строка 141: | Строка 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 == | ||
Строка 168: | Строка 244: | ||
* {{term|warnings}} — патчи, исправляющие предупреждения, выданные компилятором | * {{term|warnings}} — патчи, исправляющие предупреждения, выданные компилятором | ||
== Requires, | <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 | |||
== BuildRequires, BuildPreReq, BuildRequires(pre) == | |||
Теги <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…'') | |||
== | === buildreq === | ||
При использовании утилиты [[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 == | ||
Строка 192: | Строка 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 == | ||
Строка 226: | Строка 346: | ||
Provides: oldproject = %version-%release | Provides: oldproject = %version-%release | ||
Obsoletes: oldproject <= 0.9.1 | Obsoletes: oldproject <= 0.9.1 | ||
(Примечание: [[Реагирует ли сборочница на переименование пакетов]].) | |||
== %description == | == %description == | ||
Строка 244: | Строка 366: | ||
Макрос %setup распаковывает исходный код перед компиляцией. | Макрос %setup распаковывает исходный код перед компиляцией. | ||
Конструкция <tt>%setup</tt> в Sisyphus RPM использует флаг <tt>-q</tt> (quiet) по умолчанию. Для | Конструкция <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 | ||
Строка 256: | Строка 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 === | ||
Строка 308: | Строка 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>. | ||
Ненулевой код возврата по умолчанию приводит к останову сборки (в т.ч. и на | Ненулевой код возврата по умолчанию приводит к останову сборки (в т.ч. и на [[girar]]); это возможно изменить при помощи ключей <tt>--disable check</tt>/<tt>--without check</tt>/<tt>--disable test</tt>/<tt>--without test</tt> или макроса | ||
%def_disable check | %def_disable check | ||
Строка 319: | Строка 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 == | ||
Строка 325: | Строка 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 == | ||
Строка 335: | Строка 604: | ||
{{Main|Руководство по написанию changelog}} | {{Main|Руководство по написанию changelog}} | ||
== Примеры == | |||
{{Main|Spec/sample}} | |||
== Ссылки == | == Ссылки == | ||
* [http://docs.altlinux.org/archive/2.2/master/devel-html/ch01s02.html ALT specfile conventions] | * [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
Что такое Spec-файл
Spec - это файл, описывающий пакет RPM. Он содержит инструкции по сборке пакета и метаданные, содержащие подробную информацию о нем. В spec-файле можно выделить разделы:
- в начале принято задавать переменные и управляющие директивы RPM, которые будут использоваться в дальнейшем (см. например разделы #Работа с upstream-исходниками и #Включение/выключение подпакетов ниже).
- затем идёт преамбула или заголовок, в котором при помощи директив задаются метаданные пакета, такие как имя, версия, зависимости. Основные такие директивы описаны ниже.
- далее, при необходимости предустановочные и постустановочные сценарии %pre, %preun, %post и %postun.
- далее, секция (или несколько) %files, описывающаяя, какие файлы будут запакованы в пакет
- завершает spec %changelog.
Работа с 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
%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 сценарии. Для управления подобными ситуациями предусмотрен специальный аргумент, который содержит количество экземпляров данного пакета в системе.
Значение \ Сценарий | %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
Примеры
Ссылки
- ALT specfile conventions
- Spec/Предопределенные макросы
- Особенности написания спек файлов в ALT Linux
- SampleSpecs
- Knobs
Примечания
- ↑ Для ссылки на коммит удобен git describe --tags, который в апстримной ветке с тэгами возвращает примерно такую информацию: "1.0-10-gda39a3e", где 1.0 - это версия, 10 - это количество коммитов после тэга, da39a3e - это его хэш.
- ↑ Такой подход предложил glebfm в этом баге.
- ↑ См. rpm --eval %ix86
- ↑ http://lists.altlinux.org/pipermail/devel/2011-March/189039.html
- ↑ vsu@ в devel@