Политика оформления библиотек

Материал из Rosalab Wiki
Перейти к: навигация, поиск
Чтобы создать лучшее обновление, важно сохранить старые major версии библиотеки в системе, чтобы программы, которые их используют, продолжили работать.

Правила составления имён

Библиотеки в /usr/lib и в /lib должны быть упакованы отдельно в специальный библиотечный пакет с именем, содержащим название основной библиотеки и major (или soname, см. далее). Эти пакеты не должны содержать никаких бинарных файлов, которые должны быть в другом пакете. Пакеты могут содержать другие файлы (например, документацию или лицензию) при условии, что эти файлы установлены по адресу, специфичному для пакета (например, libfoo2 может установить что-то в /usr/share/doc/libfoo2/). Цель состоит в том, чтобы установить libfoo1 и libfoo2 в одну систему.

Прежде всего фундаментально, что исходные rpm сохраняют одно имя без какого-либо major номера, так что git репозиторий содержит только одну ветку каждого пакета.

Когда дистрибутив должен иметь две версии одной библиотеки одновременно (например, qt1 и qt2), то исходные rpm будут разделены, чтобы мы могли включить обе версии в дистрибутив в виде двух разных, независимо поддерживаемых пакетов.

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

  • Исходный пакет:
    • foo-2.3.4-4-rosa2012.src.rpm
  • Бинарные пакеты:
    • foo-2.3.4-4-rosa2012.arch.rpm
    • libfoo2-2.3.4-4-rosa2012.arch.rpm
    • libfoo-devel-2.3.4-4-rosa2012.arch.rpm

Если foo-2.3.4-4-rosa2012.src.rpm создаёт несколько библиотек, то эти библиотеки должны быть упакованы в отдельные файлы: libfoo2-2.3.4-4-rosa2012.arch.rpm, libbar2-2.3.4-4-rosa2012.arch.rpm и т.д. Однако devel файлы могут быть собраны в один пакет. Имя такого пакета может начинаться с lib, однако для 32-битных и 64-битных пакетов желательно иметь разные имена (например, foo-devel и foo64-devel). Обоснование: -devel пакеты не устанавливаются пользователем, поэтому разделение таких пакетов не влияет на пользователя, но может усложнить жизнь разработчику. Отдельные имена для 32-битных и 64-битных -devel пакетов позволяют устанавливать пакеты обеих архитектур в одной системе.

Если апстримное имя само по себе начинается с lib (например, libxml2), то пакет с бинарными файлами можно назвать libfoo-utils или libfoo-tools или как-то похоже, чтобы можно было отличить его от пакета библиотеки.

Названия для x86_64

  • Бинарные пакеты:
    • foo-2.3.4-4-rosa2012.x86_64.rpm
    • lib64foo2-2.3.4-4-rosa2012.x86_64.rpm
    • lib64foo-devel-2.3.4-4-rosa2012.x86_64.rpm

Чтобы было проще, используйте %mklibname:

%mklibname

Макрос %mklibname используется для создания имён библиотечных пакетов:

  •  %mklibname [-d [-s]] name [[api] major]
    • -d - создание имени для devel пакета
    • -s - создание имени для static пакета (использовать вместе с -d)
    • name - имя библиотеки (обратите внимание, что если именем библиотеки является libfoo, то надо вводить foo, а не libfoo)
    • major - основное число, которое должно быть добавлено в имя (не использовать вместе с -d, кроме особых случаев, упомянутых отдельно ниже)
    • api - если библиотека имеет, например, SONAME libfoo-1.2.so.4, то api будет 1.2, а major - 4. Результатом будет libfoo1.2_4

Примеры использования:

  •  %mklibname foo 5 => libfoo5
  •  %mklibname -d foo => libfoo-devel
  •  %mklibname -d -s foo => libfoo-static-devel

Файлы *.la

Современные libtool отлично работают без *.la файлов, поэтому эти файлы по-умолчанию отбрасываются spec-helper во время сборки. В настоящее время известно несколько исключений, которые включены в код spec-helper. Если вы считаете, что нашли ещё одно исключение, свободно обращайтесь к мейнтейнерам rpmbuild.

Особые случаи

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

  • Не забывайте всегда проверять soname библиотек (objdump -x libfoo.so.1 | grep SONAME), потому что некоторые soname содержат номер версии библиотеки. Например, libfoo-1.2.so.4. В этом случае пакет должен быть назван libfoo1.2_4-1.2.4-rosa2012.
  • Пакеты, оканчивающиеся номером, должны быть снабжены "_" перед major. Например, libfoo23_4-1.2-rosa2012 (в этом случае soname будет libfoo23.so.4).
  • Нет необходимости помещать каждую библиотеку в отдельный пакет: если пакет содержит несколько библиотек, имя можно взять из основной библиотеки пакета. Если есть проблемы с хранением библиотек в одном пакете (например, их major может отличаться), пакет должен быть разделён.
    • При разбиении библиотек, которые ранее были в одном пакете, вам может потребоваться добавить Obsoletes/Conflicts в новые пакеты, чтобы попросить Urpmi поместить их в одну транзакцию.
  • Если в дистрибутиве поддерживаются несколько версий пакета с разными major, или будущий релиз получится несовместимым по major (перестройка соответствующих pkgs не является достаточной, а требуемые изменения слишком велики) с текущей версией (например, QT3/QT4/QT5), то имя devel пакета должно содержать major. В предыдущем же случае devel субпакет новой версии обычно не содержит major, а только старые версии.
  • Некоторые приложения (например, KDE ones) содержат динамически загружаемые модули, которые не являются библиотеками. Обычно эти модули помещают в основной субпакет приложения. Но иногда лучше включать такие модули в библиотечный пакет, если их установка обычно требуется при использовании библиотеки (чтобы каждое приложение, использующее библиотеку, не требовало добавить руководство по модулям). В целом, решения должны приниматься индивидуально. Однако, если модули включены в библиотечный пакет, они должны попасть в каталог с версией (например, /usr/lib/foo-2/module.so для пакета libfoo2) , чтобы установка нескольких версий библиотеки была возможной.

Обновление пакета, который следовал старой политике оформления библиотек

Измените имя devel пакета с %libname-devel на %mklibname %name -d (без %major, хотя обычно с %api, если есть), как показано выше, и добавьте Obsoletes для предыдущего имени (%mklibname %name 2 -d или %{_lib}%{name}2-devel, где 2 - major устаревшего devel пакета). Для static-devel пакетов надо произвести замену на %mklibname %name -d -s. Если есть сомнения, свободно спрашивайте в списках рассылки ROSA.

Provides и conflicts

Пакет -devel должен как минимум содержать %name-devel = %version-%release. Если исходное имя тарбола отличается от %name, то вы также должны добавить tarballname-devel = %version-%release, для совместимости с другими rpm-системами. Если в дистрибутиве содержится несколько версий библиотеки, только последняя должна называться %name-devel. Предыдущие версии должны иметь в названии, например, %name%major-devel или %name%api-devel. Но мейнтейнер также может выбрать %name%major-devel или %name%api-devel и для нового пакета, если следующий major по исходному коду окажется несовместимым (см. Особые случаи выше).

Важно понимать, что включение Provides без информации о версии делает невозможным последующее включение информации о версии. Например, "Provides: foo-devel" - НЕ годится. Пожалуйста, используйте "Provides: foo-devel = 1.2.4-3-rosa2012".

Если в дистрибутиве содержится несколько версий библиотеки, и использовано исключение в виде добавления major в название lib -devel пакета, вам нужно добавить conflicts с другими devel пакетами, если их нельзя устанавливать параллельно. Это часто бывает, когда major изменился без переименования заголовочных файлов.


Добавление старой версии в дистрибутив

Если пакет обновлён до нового major, и будет замечено, что он не совместим с исходным кодом предыдущего релиза, и пользователи библиотеки не смогут быть прямо пропатчены для использования нового API, то старая библиотека должна поддерживаться параллельно с новой. Процесс создания на примере пакета foo, который обновляется до major 3:

  1. Копируется git foo непосредственно перед обновлением foo2 до major 3. Также изменяется Name на foo2 и имя спек-файла на foo2.spec.
  2. Добавляется 2 (major) к имени devel пакета, например, libfoo2-devel вместо libfoo-devel. Это можно осуществить добавлением параметра %major в %mklibname для %devname.
  3. Редактируются все provides, чтобы в них был major. Например, %name-devel или foo%major-devel.
  4. Добавляется Conflicts: foo-devel, если пакет конфликтует с новым devel пакетом.

Внесения каких-либо изменений в .spec для новой версии не требуется.

Пример

Вот пример спек-файла для рассматриваемого библиотечного пакета без бинарных и конфигурационных файлов. Обратите внимание, что спек-файл нерабочий. Это только пример для демонстрации разницы с обычным пакетом.

# api - это часть имени библиотеки перед .so
%define api 1.2
# major - это часть имени библиотеки после .so
%define major 1
%define libname %mklibname %{name} %{api} %{major}
%define devname %mklibname %{name} -d

#(!) summary только для SRPM
Summary:        C++ interface for popular GUI library gtk+
Name:           gtkmm
Version:        1.2.4
Release:        1

%description
#Полное и общее описание всего пакета. (Это будет только
#для SRPM)

#----------------------------------------------------------------------------

#Главный пакет (содержит только .so.[major].)
%package -n %{libname}
#(!) summary только для главной lib RPM
Summary:        Main library for gtkmm 
Group:          System/Libraries

%description -n %{libname}
This package contains the library needed to run programs dynamically
linked with gtkmm.

%files -n %{libname}
# ..
# содержит major (и api, если есть) в списке файлов, чтобы захватить
изменения при обновлении версии
%{_libdir}/lib-%{api}.so.%{major}*

#----------------------------------------------------------------------------

%package -n %{devname}
Summary:        Headers for developing programs that will use Gtk--
Group:          Development/GNOME and GTK+
Requires:       %{libname} = %{EVRD}
#(!) Не обязательно, так как мы предпочитаем использовать зависимости типа pkgconfig.
# Но если в библиотеке нет файлов pkgconfig, это необходимо
Provides:       %{name}-devel = %{EVRD}

%description -n %{devname}
This package contains the headers that programmers will need to develop
applications which will use Gtk--, the C++ interface to the GTK+ (the Gimp
ToolKit) GUI library.

%files -n %{devname}
# ..
%{_bindir}/gtkmm-config
%{_includedir}/*.h
%{_libdir}/*.so

#----------------------------------------------------------------------------

См. также

Policy for KDE 4 Libraries


Idea.png
Примечание
Эта Политика основана на Политике Оформления Библиотек Mandriva.