Home Wiki > openSUSE:Shared library packaging policy
Sign up | Login

openSUSE:Shared library packaging policy

tagline: Материал из openSUSE

Icon-obsolete.png Внимание! Оригинал статьи имеет более новую версию.
Для просмотра самой свежей информации обратитесь к английской статье. Вы можете помочь обновить статью.

Определения

- lib$NAME.so.* - разделяемая библиотека, программы могут зависеть от них, обычно существует два файла:

lib$NAME.so.$MAJOR
lib$NAME.so.$MAJOR.$MINOR.$MICRO

где lib$NAME.so.$MAJOR символьная ссылка на lib$NAME.so.$MAJOR.$MINOR.$MICRO

- SONAME - имя (можно посмотреть командой objdump -x libfoo.so.1 | grep SONAME) разделяемой библиотеки a передаваемое динамическому загрузчику. Оно совпадает с именем короткой ссылки lib$NAME.so.$MAJOR.

- lib$NAME.so - файл, используемый редактором ссылок (ld) для динамического линкования исполняемых файлов, обычно символьная ссылка на файл разделяемой библиотеки

- lib$NAME.a - статическая библиотека, используется редактором ссылок (ld) для статической линковки исполняемых файлов

- lib$NAME.la - файл конфигурации libtool используется для статической линковки с lib$NAME и динамической загрузки при помощи динамического загрузчика ltdl


Политика именования и упаковки разделяемых библиотек

Политика для предоставления соглашения об именовании разделяемых библиотек в /lib{,64} и /usr/lib{,64}. Главной целью политики является предоставления возможности существования двух (несовместимых) версий разделяемых библиотек libfoo1 и libfoo2 установленных одновременно не вызывая конфликтов в пакетном менеджере.


Именование Пакетов

  • ...разделяемые библиотеки в /lib{,64} или /usr/lib{,64} должны быть упакованы в пакеты имя которых состоит из "lib" + $NAME + $NUM.
[$NAME - формируется отрезанием префикса "lib" и суффикса ".so.*" от SONAME]
[если $NAME заканчивается на цифру, то между $NAME и $NUM вставляется тире. Вот так libfoo1-0, а не libfoo10.]
  • Разделяемые библиотеки могут находиться в /lib{,64} или /usr/lib{,64} только в случае если файлы для разработки упакован в отдельный -devel пакет для линковки с этими библиотеками. Единственным исключением является случай когда библиотека используется толкьо одним пакетом, смотрите (1) для деталей.
  • Пакеты названые lib$NAME$NUM должны содержать только файлы с именами lib*.so.* (ни заголовочных файлов, ни *.so файлов, ни файлов конфигурации, ничего другого). Смотрите ниже (3) для исключений.
  • $NUM содержит только десятичные цифры и подчеркивания.
  • $NUM равен номеру SONAME разделяемой библиотеки с точками замененными на подчеркивания. Обычно номер в SONAME равен SO версии MAJOR. Например, если SONAME это, тогда номер SONAME это 0.9.7, $NUM будет 0_9_7 в этом случае.
  • Все пакеты без суффиксов называющиеся lib* заканчиваются на $NUM.
[Общие суффиксы включая -devel или -debuginfo.]
Localize.png Эта статья содержит фрагменты на иностранном языке. Вы можете помочь переведя её до конца. (cм. руководство по переводу)
  • Packages with suffix -devel should in general omit $NUM as -devel packages for different library versions usually conflict due to common header file names. See (4a) and (4b) for how it works otherwise.

Package Contents

  • lib$NAME$NUM.rpm either contains exactly one shared library named lib$NAME.so.* or it contains multiple shared libraries.
  • lib$NAME$NUM.rpm may only contain multiple shared libraries if the SO versions of all of them change at the same time always, in lockstep.
[If depending on one of the contained libraries doesn't create a dependency on all or most other contained libraries, then it's preferred to not merge those libraries into one rpm, but leave them in their own rpm. Consider installation size. Exceptions are allowed here.]
[Example: libfoo.so.1 is packaged in libfoo1.rpm. Or libbar.so.3, a part of the program suite PLONK 4.1, would be packaged into libplonk41.rpm. The latter only makes sense if that rpm contains more than one shared library, which should be the exception, and can be done only if all shared libs therein will update their SO version in lockstep.]
  • Files needed to develop programs using shared libraries contained in lib$NAME$NUM.rpm are packaged in a -devel package (see (4a) and (4b) for cases that need to version this package). Those files include lib*.so, lib*.la and all headers. Optionally those files can also be placed in $NAME.rpm, in the case that it also comes with other tools or documentation. But _if_ there is a *-devel.rpm package then it contains all lib*.{so,la} and headers.

Best Practices

The following are guidelines for library packaging in general:

- Avoid packaging static libraries. If in doubt, ask.
- If you package a static library in addition to a shared library, the static library should not be built with -fPIC.
- If you package a static library without a corresponding shared library, the static library must be built with -fPIC.
- Avoid packaging libtool config files (.la files). In general they are not needed if you do not package a static library. If in doubt, ask.
- Shared libraries are not executable.

Exceptions

<div id="exception_1" />(1) Shared libraries which are used solely and only by programs from the containing main package must be packaged into the main rpm, without a separate lib$NAME$NUM rpm. The following must be true:

- the shared libs are placed in a subdirectory of /usr/%{_lib}/, that subdirectory is named like the main package
- no devel files for those shared libs are packaged anywhere, no *.a, no *.so, no headers, no files which normally would belong into the lib$NAME-devel package.

(2) A list of packages that are exempt from this policy is: glibc, pam (to be extended with explicit approval only).


<div id="exception_3" />(3) If a shared library package lib$NAME$NUM must contain other files than shared libraries for whatever (approved!) reason, their names must be made unambiguous by putting them in a versioned directory or by versioning their names to not conflict with the rationale of this policy.


<div id="exception_4" />(4a) If more than one version of a library is available from a single source repository even conflicting -devel packages need to be suffixed to avoid multiple packages with the same rpm name. Proper conflicts need to be added in this case as well.

(4b) If more than one version of a -devel package can be installed at the same time (for example because includes are packaged in a versioned directory and shared libraries have a versioned name like libgtk1.so.1) the -devel packages should be suffixed with a number that allows identifying the version of the library (usually this is the same number as the shared library package suffix $NUM). So such a -devel package would be named lib$NAME$NUM-devel.

Rationale

That scheme makes it possible to install and use multiple shared libraries of the same base name, but different so-version (e.g. of older distribution in case there are programs requiring them). A discriminator needs to be part of the rpm name, as otherwise the update stack will be confused, and using some monotonically increasing number as that makes sense. A strict structure on rpm names will also help those writing quick&dirty tools.

From that follows that only files should be included therein, which aren't generating file conflicts later if installed together with another libbla* rpm. Hence only lib*.so.* files are allowed in them. To ensure that no shared libraries creep in which aren't handled that way we disallow them to be in any package not named via these rules.

Effectively that creates a partition of all files into shared libs and others, and makes sure that no rpm contains files from both partitions.

Hints

You should remember the following while trying to conform to this policy:

- There is no reason why a -devel package cannot provide development files for multiple shared library packages.
- There is no need to have a binary package that matches the source package name. In fact, you should avoid renaming the source package for different versions as we prefer to only have a single package version in the source repository.
- Dependencies on the shared library package result either from automatic dependencies created by rpm on the shared libraries if they are used, or from the single other case, the library -devel package, which should require the shared library package with a properly versioned requires.
- This policy and its enforcement only is about shared library packages and shared libraries placed in /lib{,64} and /usr/lib{,64}. Rules that apply to other parts are only best practices and policies for them may exist elsewhere.

Примеры

Простейший пример это пакет исходников который собирается в одну разделяемую библиотеку и файлы разработки (пакет zlib подходит для примера). Полученые бинарные пакеты должны называться libz1 и libz-devel со следующим содержимым (список файлов сокращен), libz1:

/lib/libz.so.1
/lib/libz.so.1.2.3

libz-devel:

/usr/lib/libz.so
/usr/lib/libz.a
/usr/include/zlib.h
/usr/share/man/man3/zlib.3.gz
/usr/share/doc/packages/zlib/algorithm.txt


A more complicated example is if apart from the library and the development files there are also executables and documentation (the bzip2 package matches this example). There should be four packages (file list shortened), libbz2-1:

/lib/libbz2.so.1
/lib/libbz2.so.1.0.0

libbz2-devel:

/usr/include/bzlib.h
/usr/lib/libbz2.so
/usr/lib/libbz2.a

bzip2:

/usr/bin/bzip2
/usr/share/man/man1/bzip2.1.gz

bzip2-doc:

/usr/share/doc/packages/bzip2-doc/manual.ps.gz

where documentation may be either merged into the binary package bzip2 or the development package libbz2-devel if it is sufficiently small and related.


Another example is a library which depends on configuration or data files that can be shared with other versions of the library (the curl package matches this example). In this case the config or data files should be split into a separate package and the shared library package should require that. For example curl has the four packages libcurl4, libcurl-devel, curl and curl-ca-bundle (CA certificates required by libcurl4).