From Mageia wiki
Jump to: navigation, search

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 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 SVN 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, qt3 and qt4), 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.mga1.src.rpm
  • Binary packages:
    • foo-2.3.4-4.mga1.arch.rpm
    • libfoo2-2.3.4-4.mga1.arch.rpm
    • libfoo-devel-2.3.4-4.mga1.arch.rpm

Naming on x86_64

  • Binary packages:
    • foo-2.3.4-4.mga1.x86_64.rpm
    • lib64foo2-2.3.4-4.mga1.x86_64.rpm
    • lib64foo-devel-2.3.4-4.mga1.x86_64.rpm

The packages are likely named "lib64" on other 64 bit architectures such as aarch64.

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

Static files shouldn't be included, read Packaging_guidelines#Packaging_Static_Libraries for more details.

  • if you have *.a files, put *.a and corresponding *.la files in libfoo-static-devel,
  • *.la in non standard directories which are used to ltdl/dlopen plugins should go to libfooX (and not libfoo-devel),
  • *.la in standard directories can sometimes be used to ltdl/dlopen shared libraries, in that case those *.la should go to libfooX. You must explain in the spec file which programs are doing so, and a note in libtool archives.
  • in the other cases, put *.la in libfoo-devel (we could drop them, but the policy is not decided yet)
  • since rpm 4.17 in Mageia 9, these files are dropped by default.

cf libtool archives for explanations

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-3.mga1.
  • Packages ending with a number should be handled by putting a "_" before the major, for example libfoo23_4-1.2-3.mga1 (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.

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 cauldron mailinglist.

Provides and conflicts

At least %{name}-devel = %{version}-%{release} should be provided by the -devel package. If the original tarball name differs from %{name}, you should also provide %{tarballname}-devel = %{version}-%{release}, 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 expected 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.mga1". 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:

  • SVN 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.
  • 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}.
  • Modify any provides so that they have the major number in them. E.g. %{name}-devel or foo%{major}-devel is fine.
  • 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.

 %define name    gtkmm
 %define version 1.2.4
 %define rel     1
 # 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 develname %mklibname %{name} -d
 
 Name:           %{name}
 
 #(!) summary for SRPM only
 Summary:        C++ interface for popular GUI library gtk+
 Version:        %{version}
 Release:        %mkrel %{rel}
 
 %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:        Main library for gtkmm 
 Group:          System/Libraries
 Provides:       %{name} = %{version}-%{release}
 
 %description -n %{libname}
 This package contains the library needed to run programs dynamically
 linked with gtkmm.
 
 %package -n     %{develname}
 Summary:        Headers for developing programs that will use Gtk--
 Group:          Development/GNOME and GTK+
 Requires:       %{libname} = %{version}
 #(!) MANDATORY
 Provides:       %{name}-devel = %{version}-%{release}
 
 %description -n %{develname}
 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 %{libname}
 # ..
 # include the major number (and api if present) in the file list to catch
 changes on version upgrade
 %{_libdir}/lib-%{api}.so.%{major}{,.*}
 
 %files -n %{develname}
 # ..
 %{multiarch_bindir}/gtkmm-config
 %{_bindir}/gtkmm-config
 %{_includedir}/*.h
 %{_libdir}/*.so

More information on the library system in Linux can be found at http://www.ibm.com/developerworks/library/l-shlibs/ .


This page is released under the Creative Commons Attribution-ShareAlike 2.5 License

Authors

  • Vincent Danen
  • Anssi Hannula
  • Pascal Rigaux
  • Gustavo de Nardin