Libraries policy

From Rosalab Wiki
Revision as of 18:51, 2 February 2016 by Pulfer (Talk | contribs) (An example)

This is a page snapshot, showing old (but not deleted) versions of images and templates.
Jump to: navigation, search
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.

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)).

  • Source package:
    • foo-2.3.4-4-rosa2012.src.rpm
  • Binary packages:
    • 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

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

  • Binary packages:
    • 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

To handle this complexity, use %mklibname:

%mklibname

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

  •  %mklibname [-d [-s]] name [[api] major]
    • -d - generate a name for a devel package
    • -s - generate a name for a static package (to be used together with -d)
    • name - the library name (note that if the library name is libfoo, you should enter "foo", not "libfoo")
    • major - the major number to be appended into the name (this should not be used with -d, except in packages mentioned in special cases below)
    • api - if the library has a SONAME like libfoo-1.2.so.4, api should be set to 1.2 and major to 4. This results in libfoo1.2_4

Example usage:

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

*.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:

  • Remember to always check the soname of the libraries (objdump -x libfoo.so.1 | grep SONAME), because some sonames include the library version number, for example libfoo-1.2.so.4. In this case, the package should be named libfoo1.2_4-1.2.4-rosa2012.
  • Packages ending with a number should be handled by putting a "_" before the major, for example libfoo23_4-1.2-rosa2012 (in this case the soname would be libfoo23.so.4).
  • It is not necessary to split each library in separate packages: if a package contains several libraries, the name would be built from the main library of the package. If there are problems keeping libraries in the same package (e.g. their major may differ), the package should be split.
    • When splitting libraries which were previously in a single package, you may need to add Obsoletes/Conflicts "across" the new packages, to hint Urpmi into putting them in the same transaction (ref: libiptc and libiptables splitting)
  • If multiple versions of the package are maintained within the distro with different majors, or an expected future release is going to be source-incompatible in a major way (rebuild of concerned pkgs not being enough, and changes required are too big) with the current version (e.g. QT3/QT4/QT5), the devel package name should include the major. In the former case, the devel subpackage of the newest version should generally not contain the major, only the older versions.
  • Some applications (e.g., KDE ones) contain dynamic loading modules which are not libraries. Usually these modules are put into the main application subpackage. But sometimes it is better to include the modules in the library package if they are generally required to be installed when using the library (so that every application using the library doesn't have add manual requires on the modules). In general, decisions should be made on on a case-by-case basis. However, if modules are included in the library package, they must be in a versioned directory (e.g. /usr/lib/foo-2/module.so for a libfoo2 package) so that installation of multiple versions of the library doesn't break.

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.