![]() | ![]() |
|
1. IntroductionRPM is the RPM Package Manager. It is an open packaging system available for anyone to use. It allows users to take source code for new software and package it into source and binary form such that binaries can be easily installed and tracked and source can be rebuilt easily. It also maintains a database of all packages and their files that can be used for verifying packages and querying for information about files and/or packages. Red Hat, Inc. encourages other distribution vendors to take the time to look at RPM and use it for their own distributions. RPM is quite flexible and easy to use, though it provides the base for a very extensive system. It is also completely open and available, though we would appreciate bug reports and fixes. Permission is granted to use and distribute RPM royalty free under the GPL. More complete documentation is available on RPM in the book by Ed Bailey, Maximum RPM. That book is available for download or purchase at www.redhat.com. 2. OverviewFirst, let me state some of the philosophy behind RPM. One design goal was to allow the use of "pristine" sources. With RPP (our former packaging system of which none of RPM is derived), our source packages were the "hacked" sources that we built from. Theoretically, one could install a source RPP and then make it with no problems. But the sources were not the original ones, and there was no reference as to what changes we had to make to get it to build. One had to download the pristine sources separately. With RPM, you have the pristine sources along with patches that we used to compile from. We see this as a big advantage. Why? Several reasons. For one, if a new version of a program comes out, you don't necessarily have to start from scratch to get it to compile under RHL. You can look at the patch to see what you might need to do. All the compile-in defaults are easily visible this way. RPM is also designed to have powerful querying options. You can do searches through your entire database for packages or just certain files. You can also easily find out what package a file belongs to and where it came from. The RPM files themselves are compressed archives, but you can query individual packages easily and quickly because of a custom binary header added to the package with everything you could possibly need to know contained in uncompressed form. This allows for fast querying. Another powerful feature is the ability to verify packages. If you are worried that you deleted an important file for some package, just verify it. You will be notified of any anomalies. At that point, you can reinstall the package if necessary. Any config files that you had are preserved as well. We would like to thank the folks from the BOGUS distribution for many of their ideas and concepts that are included in RPM. While RPM was completely written by Red Hat, Inc., its operation is based on code written by BOGUS (PM and PMS). 3. General Information3.1. Acquiring RPMThe best way to get RPM is to install Red Hat Linux. If you don't want to do that, you can still get and use RPM. It can be acquired from ftp.redhat.com. 3.2. RPM RequirementsRPM itself should build on basically any Unix-like system. It has been built and used on Tru64 Unix, AIX, Solaris, SunOS, and basically all flavors of Linux. To build RPMs from source, you also need everything normally required to build a package, like gcc, make, etc. 4. Using RPMIn its simplest form, RPM can be used to install packages:
The next simplest command is to uninstall a package:
One of the more complex but highly useful commands allows you to install packages via FTP. If you are connected to the net and want to install a new package, all you need to do is specify the file with a valid URL, like so:
Please note, that RPM will now query and/or install via FTP. While these are simple commands, rpm can be used in a multitude of ways. To see which options are available in your version of RPM, type:
You can find more details on what those options do in the RPM man page, found by typing:
5. Now what can I really do with RPM?RPM is a very useful tool and, as you can see, has several options. The best way to make sense of them is to look at some examples. I covered simple install/uninstall above, so here are some more examples:
These are just several examples. More creative ones can be thought of really easy once you are familiar with RPM. 6. Building RPMsBuilding RPMs is fairly easy to do, especially if you can get the software you are trying to package to build on its own. We assume here that you know how to build software from source. If you don't you probably shouldn't be starting with this document. The basic procedure to build an RPM is as follows:
Under normal operation, RPM builds both binary and source packages. 6.1. The Spec FileWe'll begin with discussion of the spec file. Spec files are required to build a package. The spec file is a description of the software along with instructions on how to build it and a file list for all the binaries that get installed. You'll want to name your spec file according to a standard convention. It should be the package name-dash-version number-dash-release number-dot-spec. This will ensure that if you install multiple source RPMs for different versions of the same package that at least the spec files remain intact. Here is a small spec file (eject-2.0.2-1.spec):
6.2. The HeaderThe header has some standard fields in it that you need to fill in. There are a few caveats as well. The fields must be filled in as follows:
6.3. PrepThis is the second section in the spec file. It is used to get the sources ready to build. Here you need to do anything necessary to get the sources patched and setup like they need to be setup to do a make. One thing to note: Each of these sections is really just a place to execute shell scripts. You could simply make an sh script and put it after the %prep tag to unpack and patch your sources. We have made macros to aid in this, however. The first of these macros is the %setup macro. In its simplest form (no command line options), it simply unpacks the sources and cd's into the source directory. It also takes the following options:
The next of the available macros is the %patch macro. This macro helps automate the process of applying patches to the sources. It takes several options, listed below:
That should be all the macros you need. After you have those right, you can also do any other setup you need to do via sh type scripting. Anything you include up until the %build macro (discussed in the next section) is executed via sh. Look at the example above for the types of things you might want to do here. 6.4. BuildThere aren't really any macros for this section. You should just put any commands here that you would need to use to build the software once you had untarred the source, patched it, and cd'ed into the directory. This is just another set of commands passed to sh, so any legal sh commands can go here (including comments).
The variable RPM_OPT_FLAGS is set using values in /usr/lib/rpm/rpmrc. Look there to make sure you are using values appropriate for your system (in most cases you are). Or simply don't use this variable in your spec file. It is optional. 6.5. InstallThere aren't really any macros here, either. You basically just want to put whatever commands here that are necessary to install. If you have make install available to you in the package you are building, put that here. If not, you can either patch the makefile for a make install and just do a make install here, or you can hand install them here with sh commands. You can consider your current directory to be the toplevel of the source directory. The variable RPM_BUILD_ROOT is available to tell you the path set as the Buildroot: in the header. Using build roots are optional but are highly recommended because they keep you from cluttering your system with software that isn't in your RPM database (building an RPM doesn't touch your database...you must go install the binary RPM you just built to do that). 6.6. Cleaning your systemIt's a good idea to always make sure there is a clean build root before building a package a second time on a system. The %clean macro will help with that. Simply put the proper commands there to blow away a former build root. Anal, err, careful folks may want to test that RPM_BUILD_ROOT wasn't set to / before doing something this volatile. 6.7. Optional pre and post Install/Uninstall ScriptsYou can put scripts in that get run before and after the installation and uninstallation of binary packages. A main reason for this is to do things like run ldconfig after installing or removing packages that contain shared libraries. The macros for each of the scripts is as follows:
The contents of these sections should just be any sh style script, though you do not need the #!/bin/sh. 6.8. FilesThis is the section where you must list the files for the binary package. RPM has no way to know what binaries get installed as a result of make install. There is NO way to do this. Some have suggested doing a find before and after the package install. With a multiuser system, this is unacceptable as other files may be created during a package building process that have nothing to do with the package itself. There are some macros available to do some special things as well. They are listed and described here:
The biggest caveat in the file list is listing directories. If you list /usr/bin by accident, your binary package will contain every file in /usr/bin on your system. 6.9. ChangelogThis is a log of what changes occurred when the package is updated. If you are modifying an existing RPM it is a good idea to list what changes you made here. The format is simple. Start each new entry with a line with a * followed by the date, your name, and your email address. The date should appear in the same format that is output by:
The rest of the section is a free text field, but should be organized in some coherent manner. 7. Building It7.1. The Source Directory TreeThe first thing you need is a properly configured build tree. This is configurable using the /etc/rpmrc file. Most people will just use /usr/src. You may need to create the following directories to make a build tree:
7.2. Test BuildingThe first thing you'll probably want to to is get the source to build cleanly without using RPM. To do this, unpack the sources, and change the directory name to $NAME.orig. Then unpack the source again. Use this source to build from. Go into the source directory and follow the instructions to build it. If you have to edit things, you'll need a patch. Once you get it to build, clean the source directory. Make sure and remove any files that get made from a configure script. Then cd back out of the source directory to its parent. Then you'll do something like:
This will create a patch for you that you can use in your spec file. Note that the "linux" that you see in the patch name is just an identifier. You might want to use something more descriptive like "config" or "bugs" to describe why you had to make a patch. It's also a good idea to look at the patch file you are creating before using it to make sure no binaries were included by accident. 7.3. Generating the File ListNow that you have source that will build and you know how to do it, build it and install it. Look at the output of the install sequence and build your file list from that to use in the spec file. We usually build the spec file in parallel with all of these steps. You can create the initial one and fill in the easy parts, and then fill in the other steps as you go. 7.4. Building the Package with RPMOnce you have a spec file, you are ready to try and build your package. The most useful way to do it is with a command like the following:
There are other options useful with the -b switch as well:
There are several modifiers to the -b switch. They are as follows:
7.5. Testing ItOnce you have a source and binary rpm for your package, you need to test it. The easiest and best way is to use a totally different machine from the one you are building on to test. After all, you've just done a lot of make install's on your own machine, so it should be installed fairly well. You can do an rpm -e packagename on the package to test, but that can be deceiving because in building the package, you did a make install. If you left something out of your file list, it will not get uninstalled. You'll then reinstall the binary package and your system will be complete again, but your rpm still isn't. Make sure and keep in mind that just because you do a rpm -ba package, most people installing your package will just be doing the rpm -i package. Make sure you don't do anything in the build or install sections that will need to be done when the binaries are installed by themselves. 7.6. What to do with your new RPMsOnce you've made your own RPM of something (assuming its something that hasn't already been RPM'ed), you can contribute your work to others (also assuming you RPM'ed something freely distributable). To do so, you'll want to upload it to ftp.redhat.com. 7.7. What Now?Please see the above sections on Testing and What to do with new RPMs. We want all the RPMs available we can get, and we want them to be good RPMs. Please take the time to test them well, and then take the time to upload them for everyone's benefit. Also, please make sure you are only uploading freely available software. Commercial software and shareware should not be uploaded unless they have a copyright expressly stating that this is allowed. This includes ssh, pgp, etc. 8. Multi-architectural RPM BuildingRPM can now be used to build packages for the Intel i386, the Digital Alpha running Linux, and the Sparc (and others). There are several features that make building packages on all platforms easy. The first of these is the "optflags" directive in the /etc/rpmrc. It can be used to set flags used when building software to architecture specific values. Another feature is the "arch" macros in the spec file. They can be used to do different things depending on the architecture you are building on. Another feature is the "Exclude" directive in the header. 8.1. Sample spec FileThe following is part of the spec file for the "fileutils" package. It is setup to build on both the Alpha and the Intel.
8.2. OptflagsIn this example, you see how the "optflags" directive is used from the /etc/rpmrc. Depending on which architecture you are building on, the proper value is given to RPM_OPT_FLAGS. You must patch the Makefile for your package to use this variable in place of the normal directives you might use (like -m486 and -O2). You can get a better feel for what needs to be done by installing this source package and then unpacking the source and examine the Makefile. Then look at the patch for the Makefile and see what changes must be made. 8.3. MacrosThe %ifarch macro is very important to all of this. Most times you will need to make a patch or two that is specific to one architecture only. In this case, RPM will allow you to apply that patch to just one architecture only. In the above example, fileutils has a patch for 64 bit machines. Obviously, this should only be applied on the Alpha at the moment. So, we add an %ifarch macro around the 64 bit patch like so:
This will insure that the patch is not applied on any architecture except the alpha. 8.4. Excluding Architectures from PackagesSo that you can maintain source RPMs in one directory for all platforms, we have implemented the ability to "exclude" packages from being built on certain architectures. This is so you can still do things like
and have the right packages build. If you haven't yet ported an application to a certain platform, all you have to do is add a line like:
to the header of the spec file of the source package. Then rebuild the package on the platform that it does build on. You'll then have a source package that builds on an Intel and can easily be skipped on an Alpha. 8.5. Finishing UpUsing RPM to make multi-architectural packages is usually easier to do than getting the package itself to build both places. As more of the hard packages get built this is getting much easier, however. As always, the best help when you get stuck building an RPM is to look a similar source package. |