In order to enjoy better upgrades, it is important to keep old major library versions in the system so that programs which use them still work.

Contents

Naming Conventions

Libraries in /usr/lib and /lib must be separately packaged, in a library-only package, named with the name of the main library concatenated with the major of the library (or soname, see below). These packages should not contain any binaries, which should be in a different package. The packages can contain other files (e.g., documentation or license) provided that these files are installed to location specific to the package (e.g, libfoo2 may install something to /usr/share/doc/libfoo2/). The goal is to be able to install libfoo1 and libfoo2 on the same system.

First of all, it is fundamental that the source rpms keep the same name without any major number, so that the git repository contains only one branch for each package.

When the distribution must have two versions of the same library at the same time (for example, qt1 and qt2), the sources rpms will be separated so that we can include both versions in the distribution as two different, independently maintained packages.

Here's a generic example: the following happens when the library comes with binaries, config files, or anything else that won't fit in the main library package (where only libraries go) nor in the devel package (where headers and devel libraries go (e.g. .so and .a)).

If foo-2.3.4-4-rosa2012.src.rpm produces several libraries, then these libraries must be packaged in separate files - libfoo2-2.3.4-4-rosa2012.arch.rpm, libbar2-2.3.4-4-rosa2012.arch.rpm, etc. However, devel files for them can be provided in a single package. Name of such single package may not start with 'lib'; however, it is desired for 32-bit and 64-bit packages to have different names (e.g., foo-devel and foo64-devel). Rationale: -devel packages are not installed on standard end-user installations, so splitting them doesn't affect end-users but would make developers' life more difficult. Distinct names for 32-bit and 64-bit -devel packages allow to install packages for both architectures in the same system.

If upstream name itself starts with 'lib' (e.g., libxml2) then package with binaries can be named as libfoo-utils or libfoo-tools or something similar allowing to distinguish it from the library package.

Naming on x86_64

To handle this complexity, use %mklibname:

%mklibname

The %mklibname macro is used to generate the library package names:

Example usage:

*.la files

Modern libtool works fine without *la files, so these files are dropped by default by spec-helper during the build process. Several exceptions are known at the moment that are hardcoded in the spec-helper code. If you think you have found one more exception, feel free to contact rpmbuild maintainers.

Special cases

We described the default policy for library packages, however some special cases can happen and must be handled using the brain:

Updating a package which is following the old library policy

Change the name of devel packages from %libname-devel to "%mklibname %name -d" (without %major! though usually with %api if present) as seen above and add an Obsoletes for the previous name ("%mklibname %name 2 -d" or "%{_lib}%{name}2-devel", 2 being the major of the obsoleted devel package). Static-devel packages have to be switched to use %mklibname %name -d -s. If in doubt, do not hesitate to ask in ROSA mailing lists.

Provides and conflicts

At least %name-devel = %EVRD should be provided by the -devel package. If the original tarball name differs from %name, you should also provide tarballname-devel = %EVRD, for compatibility with other RPM-based systems. If multiple versions of the library are maintained within the distro, only the latest shall provide %name-devel. The older versions provided should provide %name%major-devel or %name%api-devel where applicable. The maintainer may also opt to provide %name%major-devel or %name%api-devel in the newest package as well, if the next major number raise is excepted to break source-compatibility (see the Special cases above).

It's important to understand that putting a Provides without the version information makes it impossible for later client RPM's to put a version information on dependencies, e.g. "Provides: foo-devel" is NOT enough, please use "Provides: foo-devel = 1.2.4-3-rosa2012".

If multiple versions of the library are maintained within the distro and the exception allowing the use of major in lib -devel package name is used, you have to add conflicts with the other devel package if they are not parallel installable. (this is often the case when the major changed, without renaming the headers).

Adding an old-majored version into the distro

If a package is upgraded to have a new major, and it will be noticed that it is not source-compatible with the previous release and the users of the library cannot be straight-forwardly patched to use the new API, the older library should be maintained in parallel with the new one. The creation process follows with the example package "foo", just upgraded to major 3:

  1. Git copy package "foo" from just before the major 3 update to package "foo2". Also change the Name to "foo2" and rename the spec file to foo2.spec.
  2. Add 2 (the major) to the devel package name, i.e. libfoo2-devel instead of libfoo-devel. This can be achieved by adding the parameter %major into the %mklibname call of %develname.
  3. Modify any provides so that they have the major number in them. E.g. %name-devel or foo%major-devel is fine.
  4. Add Conflicts: foo-devel if the package conflicts with the newer devel package.

No changes are needed in the .spec of the newer version.

An example

Here's an example of a specfile for a package with no binary and config files, so only library binary packages are needed. (Note that the spec file is not valid, it is only an example that shows how it works and to highlight the difference with a normal package.

# api is the part of the library name before the .so
%define api 1.2
# major is the part of the library name after the .so
%define major 1
%define libname %mklibname %{name} %{api} %{major}
%define devname %mklibname %{name} -d

#(!) summary for SRPM only
Summary:        C++ interface for popular GUI library gtk+
Name:           gtkmm
Version:        1.2.4
Release:        1

%description
#Full and generic description of the whole package. (this will be the SRPM
#description only)

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

#main package (contains .so.[major]. only)
%package -n %{libname}
#(!) summary for main lib RPM only
Summary:        Shared 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}
# ..
# include the major number (and api if present) in the file list to catch
# changes on version upgrade
%{_libdir}/lib%{name}-%{api}.so.%{major}*

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

%package -n %{devname}
Summary:        Headers for developing programs that will use Gtk--
Group:          Development/GNOME and GTK+
Requires:       %{libname} = %{EVRD}
#(!) Not mandatory, since we prefer to use pkgconfig-style dependencies.
# But if the library doesn't have pkgconfig files, this provide is a must
# %{EVRD} means %{?epoch:%{epoch}:}%{?version:%{version}}%{?release:-%{release}}%{?distepoch::%{distepoch}}
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}
# ..
%{multiarch_bindir}/gtkmm-config
%{_bindir}/gtkmm-config
%{_includedir}/*.h
%{_libdir}/*.so

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

See Also

Policy for KDE 4 Libraries


Note:
This Policy is based on the Mandriva Libraries Policy.