Foreword
It is assumed in this document that the reader is "linux-ready". He already knows the basic commands, directory structure, and has already used rpm at least for installing packages. This document is constructed as a step by step recipe to obtain an rpm package that can integrate well in the Mandrakelinux distribution of GNU/Linux, from either a previous source rpm or from a tar source. If you haven't done it yet, you should read the Cooker Web page, which explains the development process of Mandrakelinux. RPM roughly means three things:- a program intended to install or create packages,
- a format used in packages (source or binary) created by the program rpm,
- a file called package which contains either a binary or sources along with an information header about how to install/uninstall the program.
- install or upgrade a package verifying dependencies,
- while installing a package, perform actions in order to make the program installed ready to use,
- restore accidentally erased files belonging in a package,
- tell if a package is already installed,
- find to which package belongs a particular file,
- verify the current installation as to the fulfilment of dependency requirements of installed packages,
- ....
Install the software
The basics
Although RPM was originally designed to work with Red Hat Linux, it also works on other rpm-based distributions: Mandrakelinux, Suse, Conectiva, etc ; rpm is already installed on these systems. You can get the vanilla rpm distribution from Red Hat here: ftp://ftp.rpm.org/pub/rpm/dist/ The binary rpm you will build for Mandrakelinux may not work across the distributions, although Mandrake does everything possible to stay compatible with Red Hat.Building for Mandrakelinux
Building packages for Cooker (i.e. the development version of Mandrakelinux) is always subject to small patches and enhancements on the rpm program in use. Open any Mandrake-Cooker mirror and get:- The package rpm which is our patched version of Red Hat's.
- The package rpm-build which holds scripts used to build packages.
- The package spec-helper which is a tool to minimalize the specfiles by doing automatic things such as stripping the binaries and compressing the man pages.
- The package libtool which is used by some configure scripts to build shared libraries.
Preliminary tasks
Create required folders
To build packages, rpm needs a special tree in your home directory. This tree can be created with the following command: mkdir -p ~/rpm/{BUILD,RPMS/$ARCH,RPMS/noarch,SOURCES,SRPMS,SPECS,tmp}. Replace $ARCH with the architecture(s) you plan to build packages for, basically this can be i586 but also sparc/alpha/ppc. ALERT! Building RPM's as root is dangerous, because the binary files are installed on the system before being packaged, thus you must always build as normal user so you won't accidentally pollute your system. Make sure that the tree is of the form : ~/rpm/BUILD The directory where the building of sources is done. ~/rpm/RPMS The binary packages after building, sorted by target architecture. ~/rpm/RPMS/i586 The directory where i586.rpm packages will be stored. ~/rpm/RPMS/noarch Idem for noarch packages. ~/rpm/SOURCES The source files (mypackage.tar.bz2 for example). ~/rpm/SPECS The spec files we will have to construct. ~/rpm/SRPMS The source rpm after building. ~/rpm/tmp For temporary stuff that rpm will create when building your packages. The architecture directories under /RPMS are necessary to rpm. If they are not present, you'll get an error message.Add configuration files
In order to build packages for Mandrakelinux, you will need to add two configuration files in your home directory:.rpmrc buildarchtranslate: i386: i586 buildarchtranslate: i486: i586 buildarchtranslate: i586: i586 buildarchtranslate: i686: i586 .rpmmacros %_topdir YOUR_HOME_DIR/rpm %_tmppath YOUR_HOME_DIR/rpm/tmp %_signature gpg %_gpg_name Mandrakelinux %_gpg_path ~/.gnupg %distribution Mandrakelinux %vendor Mandrakesoftwhich you will have to edit to fit your name and directory. Warning, don't set %optflags, as one is already provided for you in the system-wide /usr/lib/rpm/rpmrc. In the same way, don't set %packager, so that rebuilding other people's packages won't put yourself in the Packager: field of the RPM, possibly in a public release which would direct bug reports to you instead of maintainer. Your rpm program is then setup to build packages.
Subscribe to mailing lists
Mandrake's lists (Consult Mailing list pages on Mandrakelinux pages):- changelog
- security
- cooker
- doc
- Red Hat's rpm-list: send a mail to rpm-list-request@redhat.com with subscribe in the subject line.
- Also there is a good rpm-help list you can subscribe to, rpmhelp@freezer-burn.org; consult the archive at http://www.freezer-burn.org/lists/rpmhelp.php3 update: this link seems to be dead.
Building an RPM
This graph represents the different steps one has to follow to build a rpm package. Circled numbers are references to sections of this howto.From an existing source RPM
This is generally the case for the packages which are already included in the distribution. The latest rpm files from cooker are available on many mirrors whose list is available at http://www.linux-mandrake.com/en/cookerdevel.php3 . Under the ftp hierarchy, you will find:- /SRPMS/ for source rpms,
- /cooker/Mandrake/RPMS/ for binary rpms.
- /contrib/SRPMS/ for contrib source rpms,
- /contrib/RPMS/ for contrib binary rpms.
[camille@kenobi ~/rpm]$ rpm -i /cooker/SRPMS/ktron-1.0.1-2mdk.src.rpm [camille@kenobi ~/rpm]$ ls -R * SRPMS: SPECS: ktron.spec SOURCES: ktron-1.0.1.tar.bz2 RPMS: noarch/ i686/ i586/ i386/ BUILD:We see that rpm has installed in our RPM tree the source file ktron-1.0.1.tar.bz2 and the spec file. Even before building a newer version of a package, it might be very interesting for you to rebuild the current package in order to understand how it is compiled and if it compiles. The magic command for doing this is rpmbuild with the option buildall:
[camille@kenobi ~/rpm]$ cd ~/rpm/SPECS [camille@kenobi ~/rpm]$ rpmbuild -ba ktron.spec [camille@kenobi ~/rpm]$ ls -l ~/rpm/RPMS/i586/ktron-1.0.1-2mdk.i586.rpm [camille@kenobi ~/rpm]$ ls -l ~/rpm/SRPMS/ktron-1.0.1-2mdk.src.rpmIf the build finished (it can last hours for some packages like kernels) without errors, you will get the binary rpm and the src rpm into your ~/rpm/RPMS/i586 and ~/rpm/SRPMS/ subdirectories respectively. If you want to install the binary rpm, you must act as 'root' which you can access to by typing su (and exit by typing control_d). But in order to build a rpm, as for expanding a src.rpm, you never need to be root. The log of the build might be very long and can be stored for later browsing. I am using emacs or xemacs and use a second window with a shell (Alt-x shell) and save the buffer as ktron.LOG, for example, when finished. In the ~/rpm/BUILD sub-directories you will usually access to the patched sources (if one or more patches were given in ~/rpm/SOURCES), to the binaries, compiled libraries, man pages etc. The spec file describes the source and patch files, how to build the package and how to install the package. Now all we need to do, in this case of improving ktron, is to modify the spec file and then rebuild the package. It is important to note that each package maintained at MandrakeSoft is stored on a cvs system. This allows every state of a package to be recorded by the system, so that the developer may consult the archive to check previous modifications and if necessary revert to an older release version. Each spec file is stored on a module called SPECS/ or contrib-SPECS/. You can access it on http://cvs.mandrakesoft.com/ For details on how to access cvs system, consult the Mandrakelinux CVS pages
From raw sources
You found an interesting program at freshmeat or sourceforge which warns you when the tea is ready. And you want it available to all our Mandrakelinux's English tea drinkers. Download it and place it in the SOURCES directory.Preliminary checks
- License. Some fools out there still write programs with non-GPL licenses. Check it carefully and ask whether or not it may be incorporated in the distribution. We do not accept non open-sourced software, with some exceptions for the club. Also, we cannot accept software for which the licences don't allow us to freely distribute it. Watch out for these programs. A list of licenses and acceptable software can be found on MandrakeLicence
- bz2 Compression. To save space in the package, turn every source and the patches to bzip2 format. Most of the time, the sources will be released as a .tar.gz archive. First of all, convert it to a .tar.bz2 (which will be smaller), by using bzme provided by Mandrake's bzip2 package. For high-risk security-critical packages where only non tar.bz2 source is distributed, we recommend that you don't bzip2 it it will change the md5sum. For these kind of packages we recommend that you leave it in .tar.gz form so that when someone runs md5sum on it it will match the value of the md5sum as listed at the download location. One such example where this execption may apply would be OpenSSH.
Inside the spec file
Here we are. This is the important section of this document. The spec file contains all the information needed by rpm to:- compile the program and build source and binary rpms,
- install and uninstall the program on the final user's machine.
%define name gif2png %define version 2.0.1 %define release 1mdk Name: %{name} Summary: Tools for converting websites from using GIFs to using PNGs Version: %{version} Release: %{release} Source0: http://www.tuxedo.org/~esr/gif2png/%{name}-%{version}.tar.bz2 Source1: %{name}-%{version}-mdk-addon.tar.bz2 Patch0: gif2png-2.0.1-bugfix.patch.bz2 URL: http://www.tuxedo.org/~esr/gif2png/ Group: Applications/Multimedia BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot License: MIT-like Requires: python %description Tools for converting GIFs to PNGs. The program gif2png converts GIF files to PNG files. The Python script web2png converts an entire web tree, also patching HTML pages to keep IMG SRC references correct. %prep %setup -q -a 1 %patch -p1 %build %configure %make %install rm -rf $RPM_BUILD_ROOT %makeinstall %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,0755) %doc README NEWS COPYING AUTHORS %{_mandir}/man1/gif2png.1* %{_mandir}/man1/web2png.1* %{_bindir}/gif2png %{_bindir}/web2png %changelog * Mon Nov 02 1999 Camille Begnis <camille@mandrakesoft.com> 2.0.1-1mdk - Upgraded to 2.0.1 * Mon Oct 25 1999 Camille Begnis <camille@mandrakesoft.com> 2.0.0-1mdk - Specfile adaptations for Mandrake - add python requirement - gz to bz2 compressionLet's then analyze in detail each line of this Be careful, a % at the beginning of a line may tell different things :
- the beginning of a section (prep, build, install, clean)
- a built-in shell script macro (setup, patch)
- a directive used by a special section (defattr, doc, ...)
Header section
%define name gif2png %define version 2.0.1 %define release 1mdkThese three lines define constants that may be used in many following sections of the spec file, named %{name}, %{version} and %{release}. Then, we can fill up some information fields for rpm :
Name: %{name}The name of the package as used in the package's name and in the package database on the user's machine. Note that the "%{name}" is a reference to the previous define.
Version: %{version} Release: %{release}At this points we must explain how the name of a package is formed. It is important to always respect this standard in order to make your work understandable to others. There are also some tags that you might want to know about, but which are not in the spec file example. There are some that you might encounter. It is not expected that you remember all of this if you just started building rpms, but after some time, this list makes good reference!
- A binary package is named as: name-version-release.arch.rpm
- A source package is named as: name-version-release.src.rpm (i.e. gif2png-2.0.1-1mdk.src.rpm in our example)
Summary: tools for converting websites from using GIFs to using PNGsThis line is a one-liner of the package description.
Source0: http://www.tuxedo.org/~esr/gif2png/%{name}-%{version}.tar.bz2This line tells rpm what source file to use for building this package. Note that the filename is preceded by a complete URL (which is optional) pointing to the site where the original source is available; rpm will remove the url, keep the filename only, and search in the SOURCES directory. Although we say that the complete URL is optional, it is highly recommended so people will know where to find new sources should they take a liking to upgrading the source and do a recompilation. This will allow tools like rpmbuildupdate to automatically rebuild new versions (see RpmBuildUpdate for more info). When there is more than one source file, use other lines with Source1: ..., then Source2: ..., etc.
Patch0: gif2png-2.0.1-bugfix.patch.bz2Two reasons for this optional tag:
- You fixed a bug on the program sources. So you generated a patch file to be applied to the sources before compilation. Note that the patches are all bzipped, too. Even if a patch is small you might not benefit from bzip2 compression, but it has to be bzipped to be consistent.
- You've been warned of the existence of a patch for your software's version somewhere on the net, and downloaded it.
URL: http://www.tuxedo.org/~esr/gif2png/This line (optional but highly recommended) points to the home page of the program.
Group: MultimediaThis is to tell rpm in which part of the general package tree to place this package. This feature is used with package managers front-ends such as rpmdrake or kpackage. The complete group structure to use, which is different from the one Red Hat uses, can be found on the page MandrakeGroups. It is mandatory to follow it, otherwise your package will mess with the other ones, in the package tree selection of the Mandrakelinux installer, or in package manager front-ends.
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildrootThis line is very important and cannot be omitted. It tells rpm that to install the program, it will have to use a special root directory (a fake "/") on the compiling machine. There are two reasons for this:
- When building an rpm, you don't have root access to the machine, so you cannot install the package in normal directories ;
- The installation into the working tree of a working machine will probably mess the package's files with other files, and most important, it may be dangerous if the package is already installed. A lot of people like to use /var/tmp or /tmp for the buildroot. This is not necessarily a problem if you are the only user of your machine, but if you have multiple users on your machine, and they compile the same package at the same time rpm will barf. Therefore it is important that you define %{_tmppath}, and within your own home directory!
License: MIT-likeThis tag (superseding Copyright) defines the license chosen by the copyright holder that will apply to the software being packed. In most cases it is GPL. See MandrakeLicence for complete valid licenses list
Requires: pythonThis line was added because one of the programs included in the package is a python script. It then needs python to be executed. You can put optional minimum (or equal) version, for example: Requires: python >= 1.5.1
%description Tools for converting GIFs to PNGs. The program gif2png converts GIF files to PNG files. The Python script web2png converts an entire web tree, also patching HTML pages to keep IMG SRC references correct.This is a quite special tag inside the header of the spec file, because it is a complete text made up of various lines and paragraphs, if needed. It contains the full description of the software being installed in order to help the user to decide whether he wants to install the package or not. You may be asking yourself at this point: "And what about translations?" Actually, to improve readability of spec files, translations of summary and description tags are stored in a special file called .po. These files are stored on the poSPECS module in Cooker cvs. When a new package is created, the base po file is automatically created in this module for future translations. This method implies that all text inside a .spec file is written in English. With the exception, however, of packages intended for a particular language (ispell-de for example). In that case it is recommended to have the text in two languages: English and in the language of that particular package. You will use special tags for this: Summary(de): .. and %description -l de.
Prep section
%prep %setup -q -a 1 %patch0 -p1Into this section, is written the first script being executed by rpm. Its role is to:
- create the top-level build directory (into BUILD),
- unpack the original sources into the build directory,
- apply optional patches to the sources.
%setup -q -a 1This is a buit-in script macro which
- cd's into the build tree,
- extract the source(s) (quietly, -q)
- change ownership and permissions of source files.
- -c name - switch -c wrote that upper directory is created first; then cd into this directory and then unpack Source0. This is useful when some packages are unbecomed (meaning?; DickGevers) tar.bz-ipped without parent directory.
- -D - does not delete the directory before unpacking. This is only useful if you have more than one setup macro. It should only be used in setup macros after the first one (but never in the first one).
- -T - this option overrides the default action of untarring the Source and requires a -b 0 or -a 0 to get the main source file untarred. You need this when there are secondary sources.
- -n name - if the name of the rpm is something other than what the Source unpacks to, use this switch. For example: if the rpm name is program-version-revision and the Source unpacks to the program-version-date, the rpm build process will not be able to cd into the directory program-version, so use -n program-version-date, so rpm will know the new directory in which to continue.
%patch0 -p1The macro responsible for applying the patch to the sources; its parameter "-p" is passed to the patch program. Imagine if you had another patch declared Patch1: .. in the header section, you would add another line: %patch1 -p1. Adding a -b .your_suffix would also be nice, as you can let others know what your patch does, or who did the patch. For example, if Fred did the patch, then he could do %patch -p1 -b .fred, or if Barney did the patch then it could be %patch -p1 -b .barney
Build section
%buildThis section will contain the script responsible for the actual build of the software. It consists of the commands being issued when building a package from an untarred source tree.
%configureThis is the line used for configuring autoconf'ed sources. %configure issues a ./configure with many add-ons such as export CFLAGS="$RPM_OPT_FLAGS" before the configure, and options such as i586-mandrake-linux --prefix=/usr --datadir=/usr/share etc. Sometimes these arguments are not supported by the configure script. In such case, you have to discover the reason, and issue the ./configure with appropriate parameters. Give the target platform to the configure call, if supported, with %{_target_platform}; of course, specification of an architecture must be avoided in specfiles; on ix86, this will expand to i586-mandrake-linux, as shown in the example above. Note that you will need the libtool package to use %configure with packages building shared libraries. When building, and when testing your package, you should verify that the target host is actually an i586 ; in particular, when compiling on a higher processor type, the default behaviour of the configure script is to discover your processor, and optimize for it. The target of the %configure macro is to avoid this behaviour.
%makeThis is a simple macro that basically performs a make with appropriate multiprocessor parameter -j. For sources using xmkmf, you should replace the next make with:
make CDEBUGFLAGS="$RPM_OPT_FLAGS" CXXDEBUGFLAGS="$RPM_OPT_FLAGS"For other packages, in many (but not all) cases a simple make will do.
Install section
%installThis section will contain the script responsible for actually installing the package in the simulation installation dir.: $RPM_BUILD_ROOT. It'll contain all commands necessary to make the software ready to run on the user's system.
rm -rf $RPM_BUILD_ROOTThis is the first of the commands being executed in the %install section, it cleans up a possible previous install directory.
%makeinstallThis line finally installs the software into the simulation installation directory for autoconf'ed sources. This macro will expand to "make install" with many options in order to install in the simulation directory $RPM_BUILD_ROOT, e.g. prefix=$RPM_BUILD_ROOT%{_prefix} bindir=$RPM_BUILD_ROOT%{_bindir} etc. In some cases the configure script will be partially broken and you may need to lurk in the Makefiles to guess the additional parameters to have it install correctly. One of the most common ones is that sometimes you have to use make DESTDIR=$RPM_BUILD_ROOT install. To save both disk space and download time, Mandrake uses bzip2 to compress man- and info-pages. However, this aspect is handled directly by the Mandrake custom rpm program. At this point of the spec file, older packages contained some lines like find $RPM_BUILD_ROOT%{_mandir} -type f -exec bzip2 -9f {} \; It is the same for old strip $RPM_BUILD_ROOT%{_bindir}/* || : lines: they have to be removed All this stuff is to prepare the files to be ready to be packed.
%cleanThis section is meant to clean the build directory tree, $RPM_BUILD_ROOT.
rm -rf $RPM_BUILD_ROOTThis is where the job is done.
Files section
%filesThis section consists a list of files that will be picked from our simulation directory tree to be packed into the package. See the fine manual for the different options not being used in that simple example. The file list must be written by hand in the spec file. It may be constructed by listing all files created by rpm in the build directory tree. In order to do that, issue a rpm -bi mypackage.spec in order to stop the building process just after the simulated install. Then, look in the simulated installation directory, ~/rpm/tmp/gif2png-buildroot in our case, to see which files you want to put in your package (most of the time, you will put them all). Note that you should never use find to build a list of files to include but explicitely list all files (this'll show up bugs in new versions). The only exceptions is for locales for which you should use %find_lang %{name} in %install section and replace %files by %files -f %{name}.lang (see Appendix B). Note about directory structure: The files being installed by your package "should" follow the FHS recommendations at http://www.pathname.com/fhs
%defattr(-,root,root,0755)This tag defines the attributes to be applied to each file being copied to the user's system. The four arguments given mean:
- -: all the attributes for regular files are remaining unchanged,
- root: the owner of the file is root,
- root: the group of the file is root,
- 0755: the attributes applied to all directories owned by this package are 0755 ( rwxr-xr-x ).
%doc README NEWS COPYING AUTHORSThe special tag %doc designates files being part of the documentation of the package. The said files will be placed in /usr/share/doc/gif2png-2.0.1/. This directory will be also automatically created. Files specified by %doc are relative to your untarred source directory in BUILD.
%{_mandir}/man1/gif2png.1* %{_mandir}/man1/web2png.1*It is recommended to list here also each man or info file separately. Also you may wonder why telling gif2png.1* and not gif2png.1.bz2. This is to preserve compatibility with other systems that could use gzip compression instead of Mandrake bzip. If you find such referencies to bz2 compression in spec files, change them to a wildcard. Most of the time you can even use %{_mandir}/man1/*, this will take all the files it can find.
%{_bindir}/gif2png %{_bindir}/web2pngAs you can see, you have macros for every kind of path you need. Here are the most useful ones (look at /usr/lib/rpm/macros for everything) : %{_prefix}, %{_bindir}, %{_sbindir}, %{_datadir}, %{_libdir}, %{_sysconfdir}, %{_mandir}, %{_infodir}. For games, use %{_gamesbindir} and %{_gamesdatadir}.
Changelog section
%changelogThis section is to keep track of different changes made to the package. Every new release build of the package must correspond to a paragraph in this section as well as an increase in the release number (if not in the version number). The structure of these paragraphs have to be respected as following:
* Mon Nov 02 1999 Camille Begnis <camille@mandrakesoft.com> 2.0.1-1mdk
- The first line of the paragraph begins with * and, in order, each one separated by a space:
- three letters for the day of the week,
- three letters for the month,
- two figures for the day of the month,
- four figures for the year,
- First name of the packager,
- Last name of the packager,
- e-mail of the packager between <>.
- version and release of current modifs.
- Upgraded to 2.0.1Then follows one line per modification applied to the package beginning with a -. These are examples:
- spec file stolen from korganizer. - last snapshot before release - Mandrake adaptations. - Fix bug in /etc/zsh use USERNAME instead of USER. - Remove petit bouchon which annoys other players. - Improve /etc/z* to source the /etc/profile.d/ files. - fix typo in examples directory name - fixed QT libs version requirements - add patch to handle Earl Grey tea
The build
Our spec file is finally complete. Take a long breath, sit down and type rpm -ba mypackage.spec You may also add the --clean option which cleans the BUILD directory after package building completes. Usefull if you have little disk space. There are then two possibilities for the last line of your process:- 0.01% probabilities: + exit 0
- 99.99% probabilities for other cases.
Testing an RPM
You should also check the Bugzilla pages for information about this subject.Basic tests
The first steps to perform are:- Are the rpms created in the corresponding directories with the correct names? (into ~/rpm/SRPMS/ and ~/rpm/RPMS/i586/)
- Is the information obtained from issuing the command rpm -qlivp --changelog mypackage.(src.)rpm correct?
Linting the package
Next, you have to use the "rpmlint" program, which will test various things on the package (it comes from the rpmlint package). Type rpmlint mypackage..rpm and a report on the specified package will be issued. For more precision, use the -i switch. You should check the rpm and the src.rpm. More information on the errors can be found on RpmlintErrorsInstall test
On any machine - but preferably a different one than that used for compilation - do an upgrade or an install, and then check:- Are all the expected files created at their expected places with the expected rights and owners?
- Are all the installation modifications (if any) effective?
- Are all binaries executable, and is the documentation accessible to the intended users?
Send your work
Quite an easy step! Just upload your source rpm (mypackage.src.rpm) to ftp://ftp.linux-mandrake.com/incoming/ Then send an e-mail to lenny@mandrakesoft.com in order to warn him. Additionally, you should CC it to the "Cooker" list, since Lenny is quite busy. Searching Mandrake contributers on IRC is the easiest and fastest way. They wander on #MDK-cooker and on irc.freenode.net. They can check and upload your packages. If the package amounts to just a small change to an existing spec file, or if you have just added a patch, usually the sending in of the spec difference file and any additional patch file to the maintainers will do. You can use rpmmon to find who is responsible for the packages. A cgi script who sent the same info can be found on http://ben.reser.org/mandrake/rpmmon/ .Something's going wrong?
Well, it appears that you have been reading this HowTo, which is a good beginning. If you couldn't find your answer right here, you should try in the given order:For general RPM matters:
- The official RPM-HOWTO (installed along with the rpm program on your system).
- The book from Red Hat "Maximum RPM", which is available at http://www.redhat.com/docs/books/max-rpm/max-rpm-html/.
- Post a question in the mailing list rpm-list you subscribed to a long time ago at the beginning of reading this howto.
For specific Mandrake RPM matters:
Drop a line to Mandrake's Quality Assurance, . If you feel that the information you found may be useful to others, in the scope of that document, feel free to submit your proposal to the maintainer of that document.Advanced
This topic was moved to RpmHowToAdvanced.Of Pre- and Post-installation scripts
Basics
The RPM package is in fact a bit more than a simple archive containing files to be expanded in specific directories of the host client system. The system offers to the programmer a great feature: pre- and post-installation scripts. They allow the packager to write a piece of code which will be executed on the client machine while installing or erasing the package. These scripts are made of any sh valid commands. There are four of them: There are certain caveats about these scripts which you should take into account. Number one, each must fit inside a 8192 buffer, and number two, they should be non-interactive. Anything which requires manual input from the user is wrong, as this will break non-interactive RPM installation procedures.- %pre
- %post
- %preun
- %postun
- Add a cron job running the program at fixed intervals
- Run chkconfig to run the daemon at boot time
- ...
Dealing with upgrades
The fact that a package may be upgraded, and not simply installed or removed, makes the thing a little bit tougher... The problem is that the %postun script of the update is run after the %post of the old version. So all %post stuff is lost... It is often useful to ensure that an action occurs only during an install and not during an upgrade. Likewise for an action that only occurs during an uninstall and not during an upgrade. RPM's mechanism for dealing with this is the argument that is passed to the %pre, %preun, %post and %postun scripts by default. This argument indicates the number of instances of this RPM that will be installed on the machine after the current script has completed. For example, if a new package is installed then 0 will be passed to %pre and 1 passed to %post. When the package is upgraded, 1 will be passed to %pre of the new RPM, 2 will be passed to %post of the new RPM, 2 will be passed to %preun of the old RPM and 1 will be passed to %postun of the old package. Table A-1. Value of the parameter passed to pre and post scriptsParameter \ Script | %pre | %post | %preun | %postun |
for a first time install | 1 | 1 | N/C | N/C |
for an upgrade | 2 | 2 | 1 | 1 |
for a removal | N/C | N/C | 0 | 0 |
- For install scripts (%post, %pre) check if $1 is equal to "1" then it is a first time install, not an update.
- For uninstall scripts (%postun, %preun) check if $1 is equal to "0", if yes then it is a full removal; if not it is either an upgrade or an install --force of the same package.
%postun if [ $1 = 0 ]; then // Do stuff specific to uninstalls fi if [ $1 = 1 ]; then // Do stuff specific to upgrades fiA single test is therefore enough, to call the right action at the right time.
More macros
When building RPM's for Mandrakelinux, you have more macros to simplify the specfile.- Handling the info pages. An example is the best teacher:
%post %_install_info %{name}.info %preun %_remove_install_info %{name}.info
- The menu system. (detailed presentation on MandrakeMenu )
%post %{update_menus} %postun %{clean_menus}
- Handling internationalization cleanly. The best way is not to enter by hand the .mo files that usually are in /usr/share/locale/.., but to use a special macro in the %install section, which will fill up a special file for that:
%find_lang %{name}Then you will use the file in the file list:
%files -f %{name}.lang
- Build macros. The build macros %configure and %makeinstall are quite big at the present time. They specify the prefix, but also every common directory (such as bindir, datadir, and so on); in that respect, they work flawlessly with small and medium sized packages, but always need some attention for the rest. The macro %make performs the make command with appropriate -j option to scale well with multiprocessors. If you need to call manually the ./configure script, remember to NEVER hardcode the architecture; the macro %{_target_platform} is made for that purpose (or even %{_target_cpu} , if necessary).
- Building servers. To build safer servers, we use a specific macro, %serverbuild, to be used before the actual build occurs. This allows for safer optimization flags. The %build section will often look like:
%build %serverbuild %configure %make
- Initscript macros. When you install a package which will provide it's own initscript (the files in the directory /etc/init.d), it needs to be added through a call which looks like chkconfig --add .., but not in the case of upgrades, and it needs to be restarted if already running; when uninstalling, similar (opposite) things must be done; we have specific macros to do that without a glitch:
%post %_post_service <initscript-name> %preun %_preun_service <initscript-name>
- Handling ghostfiles. Mostly with games, sometimes packages use a varying file which may even not be present. That's where ghostfiles are useful. Here's an example:
%install (...) mkdir -p $RPM_BUILD_ROOT/var/lib/games touch $RPM_BUILD_ROOT/var/lib/games/methanescores %post %create_ghostfile /var/lib/games/powermanga.hi root games 664 (...) %files %attr(664, root, games) %ghost /var/lib/games/powermanga.hiThe %create_ghostfile macro will expand to:
if [ ! -f /var/lib/games/powermanga.hi ]; then touch /var/lib/games/powermanga.hi chown root.games /var/lib/games/powermanga.hi chmod 664 /var/lib/games/powermanga.hi fi
Interaction with urpmi and rpmdrake
Sometimes it's necessary to warn the user about some particular care that should be taken when upgrading or installing a specific version of a package. rpmdrake 2.1.3-11mdk (and above) supports this: it searches in rpms for text files named README.install.urpmi, README.update.urpmi or README.urpmi, and displays them. README.install.urpmi is displayed only for installed packages; README.update.urpmi only for upgraded packages; README.urpmi is displayed in both cases.Mandrakelinux Groups
The list of groups can be found on MandrakeGroupsMandrakelinux Valid Licenses
Please see on MandrakeLicenceSpecific policies
Alternatives Policy
The way of including and naming alternative versions of a same package is detailed in AlternativesPolicyWebapps policy
The webapp policy is detailed on WebAppsGeneral policy
Consult the PackagingPoliciesCool programs to check out
- rpmbuilder is an application that can help you to generate a generic spec file from a .tar.gz source. There is an official Mandrakelinux patch available. Although it generates good specs, it is recommended that you re-check them before uploading, as after all, the spec is generated automatically.
- rpmstats will print out statistics about installed packages, helping you locate packages used very often, and packages used rarely.
- rpm-rebuilder is meant to assist you if you're willing to rebuild a whole distro. It is used to generate the logs of WeeklyBuilds.
- rpmbuildupdate allows you to easily build new version of your rpm, check RpmBuildUpdate
- patcher is a small python software easing the development of a patch on a source directory. Please see https://moin.conectiva.com.br/Patcher
- .rpmmacros: Example .rpmmacros file that should work out-of-the-box
- skel.spec: Example spec file
- libskel.spec: Example spec file for a library package
- urpmb: small wrapper around rpmbuild to easily build RPMs from spec files. It will create ~/.rpmmacros and ~/.rpmrc if not present, detects mdk, plf and jpp specs and sets vendor accordingly, and most importantly it doesn't require you to put spec files and sources in separate directories but allows you to keep one directory per project with spec and sources together. The builded RPM files will be put into ./RPMS within the current directory, putting all results into ./RPMS. You no longer need to copy stuff around, you can simply keep the spec, patches and tarballs in one directory.
Programs and bots to check rpms
Rpmlint
rpmlint is really mandatory in order to avoid the common errors in building rpm's. It is mainly designed to work with Mandrakelinux -mdk packages, but it should work for any generic RPM package. rpmlint frequent errors are explained on RpmlintErrorsDistlint
distriblint is a tool used to check the whole distribution. It is run nightly, you can see reports on http://youri.zarb.org/~misc/mdk/distlint/. Documentation can be found in the package.Usual troubles
rpm build errors
unrecognized option `--tag=CXX' Try `libtool --help' for more information The libtoolize macro is part of the %configure macro (check with rpm --eval %configure), and because there is a version mismatch, things will break. Mandrakelinux uses libtool-1.4, while KDE uses libtool-1.5 (or 1.4a?). Version 1.4 doesn't understand `--tag=CXX', so it breaks. On top of your specfile, you can define this: %define __libtoolize /bin/true When you add this define, libtoolize won't be run, and all should go well.rpmlint check errors
rpmlint frequent errors are explained on RpmlintErrors. Use the -i option to ask details for each error.Binaries have a strange i586-mandrake-linux- prefix !
add --program-prefix= (notice there is nothing after the equal sign) to the %configure call; alternatively, add transform="" to the %makeinstall call. You can also try to use autoconf2.5, with %configure2.5xLibraries don't have the "so" (libfoo.0.0.0 instead of libfoo.so.0.0.0)
This is related to libtool too. "%define __libtoolize /bin/true" will solve this issueNo X display available
Some packages require the availability of an X display during the package build. StefanVanDerEijk has detailed a workaround using XFree86-Xvfb.Some links
Other interesting sources of Mandrake RPM information
- Cybercfo's "Mandrake a la Gentoo" tute (perhaps cybercfo could paste the HTML version into this wiki please?)
-- NicolasBrouard - 23 Feb 2005 (rpmbuild -ba first section. Explaining how to rebuild an rpm even before modifying it.)
-- Main.robert.p.goldmanieee.org - 17 Jan 2005 (Fixed stale link to Maximum RPM book)
-- JohnvdKamp - 29 Dec 2004 (Add -n name switch to %setup)
-- EmmanuelBlindauer - 22 Dec 2004 (Link to all policies)
-- EmmanuelBlindauer - 08 Nov 2004 - (Add a tip for libfoo without so )
-- AngeloNaselli - 31 Oct 2004 - (fix warning.gif icon)
-- EricFernandez - 01 Oct 2004 (no X display workaround linked to Stefan's LbD page)
-- RafaelGarciaSuarez - 8 Jul 2004 (interaction with urpmi and rpmdrake)
-- GoetzWaschk - 26 Feb 2004 (alternative fix for i586-mandrake-linux prefix)
-- ChmouelBoudjnah - 16 Feb 2004 (update the ffap function for emacs and rpm)
-- JohnKeller - 06 Sep 2003 (formatting changes, extra links)
-- CyberCFO - 22 Oct 2003 (edit to agree formatting to other howtos on twiki)
-- LeonBrooks - 30 Nov 2003 (add link to cybercfo's mandrake/gentoo tute)
-- MichaelReinsch - 06 Dec 2003 (updated urpmb)
-- PascalTerjan - 22 Dec 2003 (moved rpmlint errors to a separate page)
-- OlivierBlin - 23 Dec 2003 (rpm-spec-mode.el is now in rpm-build, small note about rpm-change-group)
-- MichaelScherer - 29 Dec 2003 (moved update-alternatives to a separate page)
-- TiborPittich - 11 Jan 2004 (added description of some interesting switches in %setup macro)
-- JohnKeller - 23 Jan 2004 (style sheets)
-- FredericLepied - 07 Apr 2004 (rpmbuildupdate comment)
-- RobertVojta - 29 Apr 2004 (optional sections added, than merged with dealing with upgrade)
-- MichaelScherer - 01 Jun 2004 (added some links and various fixes).
-- DickGevers - 25 Jan 2005 (fixed some typos, idiom)