RPM: синтаксис spec файла

Материал из Rosalab Wiki
Перейти к: навигация, поиск
This is the policy covering RPM spec files in ROSA Desktop. It is currently a work-in-progress proposal, based loosely off the Annvix Spec Files policy.

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

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

Подробнее о политиках, например, о политиках сборки библиотек, политике альтернатив и т. п. см. раздел политики сборки пакетов.

Заголовок (Spec Header)

Заголовок Spec-файла содержит важную информацию, необходимую для сборки, о версии пакета, исходном коде, патчах, зависимостях.

Определение макросов

В начале Spec-файла содержатся определения макросов. Например:

%define major           0
%define libname         %mklibname aide %{major}

Все %define должны быть определены именно в этом месте с соответствующими комментариями. Для выравнивания макроопределений используется табуляция как показано выше (используйте двойную табуляцию после определения name или столбец 25 (конец третьей табуляции); это позволит использовать более длинные имена в определениях). Если имя определения длиннее и следующий символ табуляции будет находиться за 26-й колонкой, используйте одиночный пробел, например:

TODO: привести данный пример
Idea.png
Примечание
Определение макросов для имени (name), версии (version) и релиза (release) не имеет смысла, поскольку эти сущности определяются через соответствующие тэги.

Название, версия, релиз

Первый раздел должен содержать стандартное название, версию и тэг релиза:

Name:    aide  
Version: 0.13.1
Release: %mkrel 1

Краткая сводка, название, исходники и патчи

Следующий раздел заголовка должен выглядеть следующим образом:

Summary:        Advanced Intrusion Detection Environment  
License:        GPLv2+
Group:          Monitoring
URL:            http://sourceforge.net/projects/aide
Source0:        http://prdownloads.sourceforge.net/aide/%{name}-%{version}.tar.gz
Source1:        http://prdownloads.sourceforge.net/aide/%{name}-%{version}.tar.gz.asc
Source2:        aide.conf
Source3:        aidecheck
Source4:        aideupdate
Source5:        aideinit
Source6:        aideinit.8
Patch0:         some.patch

Как видите, всё располагается в линейном порядке:

  1. Summary — краткое описание пакета (в одну строку).
  2. License — см. политика лицензирования.
  3. Group — принадлежность пакета к одной из групп Mandriva.
  4. URL — домашняя страница ПО.
  5. Source0... — исходники.
  6. Patch0... — патчи.

Файлы исходников должны начинаться с Source0, не используйте Source:; если в пакете содержится один единственный исходник, используйте Source0, поскольку нет гарантии, что в пакете всегда будет использоваться один исходник. Тоже самое относится к ключевому слову Patch0; всегда начинайте с Patch0:, и никогда не используйте Patch:. Если исходный код имеет URL, по которому его можно получить, то эту информацию необходимо включить.

Табуляции здесь чуть короче, чем определения, главным образом потому, что определения могут быть длиннее, но Source, Name и др. тэгов это не касается. Вместо столбца 25, используйте столбец 17 или конец второй табуляции. Важно, чтобы все значения ключевых слов, и вообще содержимое второй колонки, было выровнено по левому краю, поскольку такое оформление наиболее удобно для чтения.

Наименование патчей

Патчам должны даваться имена в очень ясной манере, чтобы можно быть быстро понять, какая версия патча была применена и откуда он был взят. Поэтому патчи должны удовлетворять следующему соглашению о наименовании: [название_пакета]-[версия]-[исходник]-[описание].patch:

  • [название_пакета] — название пакета, к которому применяется данный патч, например, Шаблон:Пакет или Шаблон:Пакет;
  • [version] is the version of the program this patch was developed against, such as 1.0. If a patch is rediffed because the old patch does not apply to a new version, a new patch must be created with the appropriate name -- it is inappropriate to rediff foo-1.0-mdv-fix.patch against foo-1.2 and continue to use the same patch name. The new patch must be named foo-1.2-mdv-fix.patch. For historical purposes, patches should be moved in svn; instead of doing "svn rm foo-1.0-mdv-fix.patch" and "svn add foo-1.0-mdv-fix.patch", the original patch should be moved and then the newly-derived patch copied and committed; i.e. "svn mv foo-1.0-mdv-fix.patch foo-1.2-mdv-fix.patch; svn commit; cp ~/foo-1.2-mdv-fix.patch ."
  • [исходник] — апстрим исходника, откуда был взят патч. Патчи изготовленные Mandriva имеют [источник] mdv. Патч, взятый из Fedora, но изменённый rediff для работы с Mandriva, должен использовать в поле [источник] mdv-fdr. Патч, взятый из апстрима CVS должен использовать cvs. This makes it very obvious where a patch has come from and who has made modifications to it; a foo-1.0-mdv-avx-owl-tmpfix.patch would indicate the patch originated from Openwall (owl), was modified at some point by Annvix (avx), and further modified by Mandriva (mdv).
  • [описание] — краткое описание патча.

Build Root, Requires, etc.

The next part of the RPM spec are the build requirements and this is perhaps one of the messiest and potentially inconsistent part of any spec. BuildRequires should be listed one per line for maximum readability; instead of cramming multiple BuildRequires on a single line, use one BuildRequires tag per dependency. While RPM may be able to quickly "view" that really long line of BuildRequires, humans cannot and while this may make the spec longer, it makes it easier to read.

Likewise, the BuildRoot tag is largely inconsistent. It should be defined as "%{_tmppath}/%{name}-%{version}"; there is no need to specify a "-root" or "-buildroot" suffix. This should remain consistent across specs. For instance:

BuildRequires:  flex
BuildRequires:  glibc-devel
BuildRequires:  glibc-static-devel
BuildRequires:  mhash-devel
BuildRequires:  zlib-devel
BuildRequires:  bison
BuildRoot:      %{_tmppath}/%{name}-%{version}


Requires, Obsoletes, Provides, Conflicts, etc.

The last set of tags in the RPM header are for Requires, Obsoletes, Provides, Conflicts, etc. and they should be defined one per line as with BuildRequires.

Requires:       gnupg
Requires(pre):  foo
Requires(postun): foo
Conflicts:      tripwire
Provides:       AIDE+gpg
Obsoletes:      bar

Again, keep the tab stops in mind. When using "Requires(postun)" you will progress beyond the tab stop at column 17; in these instances use a single space.

Also note the ordering. Instead of mixing Requires and Provides, keep them in a distinct order:

  1. Requires, Requires(pre), Requires(post), etc. -- all requires should come first, one per line
  2. Conflicts -- all conflicts come second
  3. Provides and Obsoletes -- all provides and obsoletes come third, and may be intermixed as they tend to be closely related


Описание

Тэг %description находится в самом конце, в нём содержится описание пакета. Длина строки должна составлять 76 символов.

В итоге, RPM-spec должен выглядить следующим образом:

Name:			aide
Version:		0.13.1
Release:		%mkrel 1

%define major		0
%define libname		%mklibname aide %{major}
%define somereallylongname foo

Summary:        Advanced Intrusion Detection Environment
License:        GPLv2+
Group:          Monitoring
URL:            http://sourceforge.net/projects/aide
Source0:        http://prdownloads.sourceforge.net/aide/%{name}-%{version}.tar.gz
Source1:        http://prdownloads.sourceforge.net/aide/%{name}-%{version}.tar.gz.asc
Source2:        aide.conf
Source3:        aidecheck
Source4:        aideupdate
Source5:        aideinit
Source6:        aideinit.8
Patch0:         some.patch

Buildrequires:  flex
BuildRequires:  glibc-devel
BuildRequires:  glibc-static-devel
BuildRequires:  mhash-devel
BuildRequires:  zlib-devel
BuildRequires:  bison
BuildRoot:      %{_tmppath}/%{name}-%{version}

Requires:       gnupg
Requires(pre):  foo
Requires(postun): foo
Conflicts:      tripwire
Provides:       AIDE+gpg
Obsoletes:      bar

%description
AIDE (Advanced Intrusion Detection Environment) is a free alternative to
Tripwire. It does the same things as the semi-free Tripwire and more.  It
is a file system integrity monitoring tool.

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

%prep

Раздел %prep находится после всех определений пакета. По крайней мере 2 пустые строки должны отделять конец раздела %description от %prep. Простейший раздел %prep выглядит следующим образом:

%prep
%setup -q

Другие соглашения

Далее приводится список остальных соглашений, соблюдаемых в spec-файлах Mandriva Linux.

%mkrel

Макрос %mkrel должен использоваться всегда, и должен выполняться в определении Release:

Release:		%mkrel 1

Любое использование макроса %{subrel} должно выполняться до определения Release:

Name:			aide
Version:		0.13.1
%define subrel          1
Release:		%mkrel 1

Системные макросы и макросы пользователя

Системные макросами являются макросы, определённые в файлах Шаблон:Файл и включает %mkrel, %_install_info и др. Системный макрос - это нечто выполняющее что-либо или вычисляющее что-либо. Т. е. системный макрос это не простое определение, например как %{_tmppath}, которое просто переводит путь. Системные макросы записываются без фигурных скобок, например, %mkrel, а не %{mkrel}. Макросы, определённые пользователем, которые включают в себя %{_tmppath} или %{_bindir} записываются в фигурных скобках, например, %{_tmppath}, а не %_tmppath. Если все будут использовать данное соглашение о фигурных скобках, это упростит чтение spec-файла.

Если вы не уверены, использовать ли фигурные скобки, помните, что макросы, подобные %{_libdir}, отдают значение (в данном случае, Шаблон:Файл), в то время как макрос, подобный %_install_info, действительно выполняет некоторый код.

Idea.png
Примечание
  • Используйте %{_libdir}, в не %_libdir.
  • Используйте %_install_info, а не %{_install_info}.
  • Пользуйтесь приведёнными рекомендациями и все spec-файлы станет гораздо легче читать.

Стандартные макросы

При условии использования сходных названий для макросов повышается читабельность spec-файла.

  • %{upstream_name} — если апстрим-название отличается от названия пакета.
  • %{upstream_version} — если апстрим-версия отличается от версии пакета.

Переменные

Переменные, которые действительно являются переменными, например $RPM_OPT_FLAGS или $RPM_BUILD_ROOT, не должны использоваться. Вместо них должны использовать макросы, подобные %{optflags} и %{buildroot}. Переменные "$*" относятся к конструкциям оболочки, но не к RPM-определениям.

Variables which are really definitions, such as $RPM_OPT_FLAGS or $RPM_BUILD_ROOT must not be used. Macros like %{optflags} and %{buildroot} must be used instead. Keep "$*" variables strictly limited to shell constructs and not RPM-based definitions.

Журналы изменений

Журналы изменений хранятся в журналах SVN. При выполнении коммита в svn журнал становится частью итогового spec-файла (т. к. журналы коммита создают журнал изменений RPM во время сборки). Делайте записи в журнале достаточно подробными, чтобы позднее не приходилось использовать diff ддя просмтра изменений. Пример плохой записи в журнале:

- fixed foo

Подобная запись ни о чём не говорит и, кто бы ни сделал это изменение, он не сможет сказать, что же было сделано в этом коммите. Вместо этого нужно было записать что-то в этом духе:

- rediffed description.patch to fix foo
- added foo-manpages.tar.bz2 to provide such and such for foo
- dropped cvsfix32.patch; merged upstream

Такая запись в большей степени информирует о сделанных изменениях. Заметьте, что исходники должны ссылаться на свои полные имена (как в примере: вместо S23 используется длинное имя foo-manpages.tar.bz2). Патчам нет необходимости ссылаться на полные имена, но могут ссылаться на часть описания патча. Например, первый комментарий "rediffed description.patch to fix foo", где description.patch

The above is far more telling as to what was actually done. Note that source files must be referred to by their full name (in the above, foo-manpages.tar.bz2, not "S23" or something similar). Patches do not need to be referred to by their full names, but can be referred to by the "description" portion of the patch. For instance, the first comment is "rediffed description.patch to fix foo", where description.patch is noted. The patch could in reality be named foo-1.2-mdv-description.patch; the prefix (foo-1.2-mdv) can be dropped as it should be fairly straightforward to determine what patch has modified/added/removed based on the unique description of the patch. If the patch name is not unique (i.e. there is foo-1.2-mdv-description.patch and foo-1.0-cvs-description.patch), then one of the patch names can (and probably should) be changed or the entire patch name should be noted in the changelog.

Do not refer to source files or patch numbers numerically (i.e. using S23 or P12) as patches and source files may be renumbered from time to time and a patch number is not guaranteed to remain consistent.

Обработка исходников

Файлы исходного кода обычно обрабатываются макросом %{SOURCExx}, но это неэффективно по нескольким простым причинам:

  • нет необходимости прыгать вверх-вниз по spec-файлу, чтобы найти, что, например, обозначает %{SOURCE12};
  • файлы исходного кода можно легко перенумеровать без необходимости внесения многочисленных изменений.

Вместо, в spec-файле предпочтительно использовать %{_sourcedir}/foo, т. к. это упрощает чтение файла. Например, сравните:

Source12:	something
...
install -m 0644 %{SOURCE12} %{buildroot}%{_sysconfdir}/pam.d/

с:

Source12:	something.pam
...
install -m 0644 %{_sourcedir}/something %{buildroot}%{_sysconfdir}/pam.d/

Файлы исходного кода не должны содержать макросов %{version} и %{name}, если только они не являются оригинальными файлами исходного кода из апстрима.

Файлы патчей никогда не должны содержать макросов %{version} и %{name}.

Ресурсы

Possible Changes/Suggestions Based on Proposal

This section details some technical changes that are not part of the proposal but may need to be implemented to make the proposal most effective:

  • Create a macro (%cleanbuildroot) to automatically clean the buildroot, or have %install or %clean automatically clean the buildroot without having to be specified explicitly
  • Drop BuildRoot from spec file (works since mdv2008.0, in mdv2008.1 it uses %defaultbuildroot). nb: this breaks compatibility with other/older distros

RPM spec file syntax (анг.)