Mandriva

Mandriva Rpm HOWTO, advanced section

This document covers several advanced topics not necessary to build your first RPM package. You should be familiar with the RPM package building basics before proceeding.

Menu system

The menu system is detailed on MenuSystem.

Package building switches

You can specify package building switches, as explained on SpecfilesSwitch

Renaming a package

If you need to rename a package, please follow the instruction of RenamingPackage

Library policy

Naming convention

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.

Libraries in /usr/lib, /lib and /usr/X11R6/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.

In the first time it is fundamental that the sources rpm keep the same name without any major number, so that the CVS repository only contains one branch for each package.

When the distribution must contain 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 case 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-4mdk.src.rpm
  • Binary packages:
    • foo-2.3.4-4mdk.arch.rpm
    • libfoo2-2.3.4-4mdk.arch.rpm
    • libfoo2-devel-2.3.4-4mdk.arch.rpm
When replacing an existing "foobar" package with a new package "libfoobar3", and foobar contains no binaries or configuration files, libfoobar3 should obsolete foobar. This is often the case for simpler libraries.
  • Source package: foobar-3.1-7mdk.src.rpm
  • Binary Packages:
    • libfoobar3-3.1-7mdk.arch.rpm
    • libfoobar3-devel-3.1-7mdk.arch.rpm

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-3mdk.
  • Packages ending with a number should be handle with a "_" before the major, for example libfoo23_4-1.2-3mdk (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 build with the main library of the package. If there are problems keeping libraries in the same package, the package should be splitted.

Provides and conflicts

It is important to supply some Provides, for a number of reasons:

  • Concerning the -devel package, most of the time the client app will only want to put libfoo-devel in the BuildRequires, without any version information.
  • For compatibility with other RPM-based systems, it's important to provide the original (canonical) package name (as shown in the example below). 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-3mdk".
You should also add Conflicts in devel package when they can't be simultaneously installed with -devel packages for the previous distribution release (this is often the case when the major changed, without renaming the headers).

An example

Here's an example of 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 a example that show how it works and to highlight the difference to a normal package.

%define name    gtkmm
%define version 1.2.4
%define release 1
%define lib_name_orig lib%{name}
%define lib_major 1.2
%define lib_name %mklibname %{name} %{lib_major}

Name:           %{name}

#(!) summary for SRPM only
Summary:        C++ interface for popular GUI library gtk+
Version:        %{version}
Release:        %mkrel %release

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

#main package (contains *.so.[major].* only)
%package -n     %{lib_name}

#(!) summary for main lib RPM only
Summary:        Main library for gtkmm
Group:          System/Libraries
Provides:       %{name} = %{version}-%{release}

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

%package -n     %{lib_name}-devel
Summary:        Headers for developing programs that will use Gtk--
Group:          Development/GNOME and GTK+
Requires:       %{lib_name} = %{version}
#(!) **MANDATORY**
Provides:       %{lib_name_orig}-devel = %{version}-%{release}
#(!) **MANDATORY**
Provides:       %{name}-devel = %{version}-%{release}

%description -n %{lib_name}-devel
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.

%post -n %{lib_name} -p /sbin/ldconfig
%postun -n %{lib_name} -p /sbin/ldconfig

%files -n %{lib_name}
# ..
%{_libdir}/*.so.*

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

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

Deeper inside the specfiles

Tags

Here is a list of other tags that you might see, some that you will see often, some not.

  • Prefix: This is for package relocation. It should NOT be used if your package is not relocatable. Don't be fooled! Prefix: does not define where a package should go. To specify you want the prefix to be /usr, all you need to do is put Prefix: /usr, and rpm will verify that every files in the packages does start with /usr; if this verification succeeds, the package will be marked as relocatable.
  • Requires: What is required for the binary package to run. Be advised that RPM will compute the dependencies on dynamic libs and Perl modules automatically, so to keep te spec as clean as possible you should put only what RPM will not detect automatically.
  • BuildRequires: What is required by this package in order to be built. For example, for an ncurses-based application, you would probably want to put ncurses-devel. A package version can be specified using operators such as =, > or <. If a build requirement is missing, the package build will fail.
  • BuildConflicts: What should not be installed on the machine for the package to be built.
  • Provides: This is used to provide a symbolic name (also called "virtual" packages). For example, apache provides "webserver", wu-ftpd and proftpd provide "ftpserver" (so any package that requires an FTP server can list "ftpserver" in its Requires: field).
  • Conflicts: A list of packages that can't be simultaneously installed with this package. Versions can be specified using operators.
  • BuildArchitectures: Specify specific arch to build this package, and let RPM bail out with errors if one of the Architectures is not the one specified in the list.
  • ExclusiveArch: Can only build on the specific architecture specified. Packages like MILO, the Alpha equivilant of LILO, will need this.
  • ExcludeArch: Exclude the specified archs.
  • ExclusiveOS: We really don't know why the heck you would need to use this. This excludes a piece of software from a a particular operating system.
  • Epoch: (supersedes Serial) Sometimes, naming scheme has been done the wrong way and the authors goes back to an earlier version. In this case, you need the Epoch: tag with a number. This number will take over the versioning comparison, when rpm has to guess whether a given package is newer than another. Please see next section? for how to name packages released via pre-versions.

Macros

There is also some interesting macros to note. Say you wanted to do something, but not on every platform. You can do this within RPM with the conditional macros:

%ifarch alpha sparc ppc
%patch0 -p1
%endif

The explanation: only apply the patch if the architecture is alpha, sparc, or ppc. It is not limited to using here, for example you can include this in your %files section if you so wish. Note: it is considered good behaviour to apply a platform specific patch to all platforms, unless it really breaks on another platform.

RPM command-line parameters

So you know that you can use rpm -ba to build a package. But you have more to play around with:

  • rpm -bp: stops after completion of the %prep section. Basically, it uncompresses the sources and applies the relevant patches.
  • rpm -bc: stops after completion of the %build section. Generally involves the equivalent of "make".
  • rpm -bi: stops after completion of the %install section. Well, do you have to use -ba to build again? No! All is not lost. The Mandrake RPM system has been specially patched to allow the -bi option to work with --short-circuit, which will basically resume the process. So, let's say you screwed up your %files section, and now you have fixed it, you don't have to build again from -ba. You can just use rpm -bi --short-circuit file.spec, and then rpm -ba --short-circuit file.spec to build it. Bear in mind, this is for advanced users ONLY as it is very easy to build a broken spec if you do that. * rpm --eval %macroname can evaluate a particular RPM macro. This seems to be an undocumented feature in the RPM 3.0.x series. For example, if you would like to find the %packager macro stands for, do: rpm --eval %packager.

Dependency issues

Automatic Requires

rpmbuild will add automatically some Requires to some of the packages you compile; e.g. for perl packages, it will try to find dependencies on other modules and add them as perl(Some::Other::Module). If you want to avoid some of these automatic dependencies to be added, use the _requires_exceptions macro. For example:

%define _requires_exceptions perl(Foo::Bar)\\|perl(Acme::Buffy)

Releasing pre-versions

Sometimes, program naming schemes are good, but rpm is lost. For example, with Proftpd, Pre-releases are named with the version followed by the suffix pre and then the pre version number, like so: 1.2.0pre5. Because of string comparisons, rpm thinks that 1.2.0pre5 is newer than 1.2.0 (we know that this is not true).

To permit upgrades to newer packages, we must help rpm to know which packages are newer than others. We could use the Epoch: tag (superseding the Serial: tag) but this is dirty. You have to use another naming convention, putting the "pre" stuff in the release tag; in our example you will call the package "1.2.0-0.pre5.1mdk". Then, when 1.2.0 comes out, you'll release "1.2.0-1mdk", and this package will be able to upgrade the pre5.

Alternatives

update-alternatives is described on UsingAlternatives.

Signing your packages

Security-concious people sign their packagesas signing makes it possible to verify that the packages have not been altered, and to verify who created them. The GNU Privacy Guard (GPG) is already included in the standard distribution. We recommend that if you wish to sign you use GPG to sign but RPM supports PGP as well.

First you will need to install GPG . Now read the documentation. As with most *nix applications these come with good documentation. Generate a key, and then extract the ASCII key to a plain text file:

$ gpg --gen-key

You will be prompted to choose key types and key sizes (the defaults are fine), and for a passphrase (which allows you to secure your key more, so make it quite long, but something you will never forget).

Now, add 2 lines to your ~/.rpmmacros:

%_signature gpg
%_gpg_name Your_Signature_Name

To sign your RPM packages while building, you can use the --sign argument. To add one to an existing RPM, do rpm --addsign file.rpm. To resign an existing one, use the --resign option.

For people to be able to verify the packages, they need a copy of your gpg public key. The easiest way to do this is to make an ascii-armored public key file, which you can do with:

$ gpg --armor --export "Your_Signature_Name" > gpg-public-key.asc

You should make this file available, either by uploading to a public key server, or by publishing on a web server.

More on the files section

Sometimes setting the permissions of the installed files for RPM is not always %defattr(-,root,root). You can set individual permissions for files, with the %attr() macro. %attr follows a similar format to %defattr, except that %attr is put in front of the filename.

To tell RPM that the file specified is a configuration file, place a %config at the front of the file. That way, RPM will upgrade the file, but save a copy of the old one (with the extension .rpmsave). Most of the time, it is NOT the desired behaviour, because you shall lose (temporarily) your precious configuration in exchange of the default one which is obviously far poorer than what you need. To address this issue, use %config(noreplace): it indicates that the file in the package should be installed with extension .rpmnew if there is already a modified file with the same name on the installed machine.

The %config(missingok) indicates that the file need not exist on the installed machine. The %config(missingok) is frequently used for files like /etc/rc.d/rc2.d/S55named where the (non-)existence of the symlink is part of the configuration in %post, and the file may need to be removed when this package is removed. This file is not required to exist at either install or uninstall time.

The %ghost tag on a file indicates that this file is not to be included in the package. It is typically used when the attributes of the file are important while the contents is not (e.g. a log file).

More on subpackages

To split off into a subpackage you can specify %package foo where foo is the suffix that will be added to the main package name.

For example, if your main package name is fred, and you have a %package alice line , then your subpackage will be called fred-alice. You will need to add in the corresponding name in the %description and %files, for example, %description alice, %files alice.

If you don't wish to have RPM inherit the name of your main package as the prefix of the subpackage, you can specify the -n argument to %package, like so: %package -n mysubpackage. You will need to add -n for all other relevant RPM entries as well such as %description, %files and the RPM scripts. One such application of this would be the library policy mentioned earlier.

What to avoid

This subsection is for experienced RPM builders -- to be sure that they do not miss the point.

  • Avoid any reference to $RPM_SOURCE_DIR. When using multiple sources, some people tend to reference these sources using this tag. This should be avoided and replaced by %{SOURCE2} for the Source2: source, for example.
  • Avoid to do tricky/clever/strange things in the specfile without documenting it. Most of the time, putting a comment on the line before, with your initials, is very helpful for future re-packagers, in the following style:
# (gc) I want to grab the xmms-config built in .., for bootstrapping nicely
export PATH=".:$PATH"

Locale specific packages

Some packages are only meant to be used together with special localization(s). For example, cttex, a Thai word separator program, will be useless when you don't use your system in Thai.

For such packages, you need to put an explicit Requires: on the corresponding locale package (here, locales-th). With these information, the installer will be able to change the rates of the packages according to selected internalization configuration, so that the necessary packages get installed.

Hacking rpm macros

If you understand what is a macro, you understand how to ask to rpm to do what you want. Here I report some more or less internals macros you can overwrite for some hacking stuff

Building macros

  • %_topdir: The dir for building rpms, user should always define it in ~/.rpmmacros. Default value is %_usr, aka /usr/src/RPM.
  • %_rpmdir: where binaries rpms will be stored, default value is %{_topdir}/RPMS,
  • %_srpmdir: where sources rpms will be stored, default value is %{_topdir}/SRPMS,
  • %_sourcedir where the sources files are located, default value is %{_topdir}/SOURCES,
  • %_builddir: where build will made, ie the dir where sources files are expand and build, default is %{_topdir}/BUILD,
  • %_specdir: where spec will be located when a source rpm is installed, default is %{_topdir}/SPECS,
  • %_tmppath: where temporary rpm's files will be stored, it is used for build script and in mdk scripts it is used to set %buildroot. The default value is %{_var}/tmp.
  • %_rpmfilename: Define the filename to use for binary rpms, default is %{ARCH}/%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm. This file will be store in %_rpmdir. NB: there is no macros for source rpm, internally rpm will always source using NAME-VERSION-RELEASE.src.rpm.
  • %___build_cmd: This macros define program which will run building script. rpm will evaluate %___build_cmd SCRIPT_FILE and exec it. Default is "/bin/sh -e"
rpmdb macros
  • %_dbpath: the location of rpm database into the system, this macros is internally define at build into rpm binary. The default value for Mandrakelinux (and surrely other linux) is /var/lib/rpm. You can overwrite it to create and use another database. NB: Do not change it if you plan to repare a system into a chroot, using --root is better.

The %check section

If the source comes with self-tests (i.e. "make test" or "make check" targets) you can put them in a fake %check section between %build and %install (its place is important). Then, to rebuild the rpm without executing checks, you can do :

rpm -ba --define 'check exit 0' foobar.spec

Packages maintained in CVS

Some packages are maintained in CVS and cannot be uploaded with the usual procedure. For these packages the .spec file start with the following 2 lines to warn the packager that a different procedure must be used:

# Changed by Makefile of cvs.
# Please change this file only in cvs!

To update this package use the procedure described on RpmFromCvsGuideline

Easy handling of differences between two RPM packages

The urpmdiff tool, available in contribs, allows to produce a report of differences between two rpms. The manpage has more information.

To become a Jedi, use Emacs you have to

In a nutshell, Emacs can automate much of the work, with appropriate configuration file. A good start is rpm-spec-mode.el which is now provided by the package rpm-build (it used to be Chmouel's one).

Once installed, in addition to nice syntax highlighting, you'll increase the release tag with C-c r, add a new changelog entry (with your name, email address, correct version and release tag) with C-c e; you will even visit the bzipped patches (granted you have jka-compr and ffap) with minimal pain ! M-x rpm-change-group allows to add/modify a group by browsing the list of available groups. And much more...

You can customize a lot Emacs when you know a little bit of Emacs-Lisp see this page for some useful functions.

-- RafaelGarciaSuarez - 24 Apr 2005 Talk about %check and urpmdiff

-- ClaudioMatsuoka - 09 Apr 2005 Minor changes for better content organization and overall site style consistency (not finished).

-- ChmouelBoudjnah - 27 Mar 2005 Emacs customizations.

-- RafaelGarciaSuarez - 10 Nov 2004

-- MichaelScherer - 01 Jun 2004

KB - Como fazer rpms Mandriva (pt) > Mandriva Rpm HOWTO, advanced section
Versão a mostrar 1.12 last modified by Juergen_HARMS on 14/06/2006 at 18:42


Criador: jamaique on 2005/07/20 16:27
(c) Mandriva 2007
18888888