How to customize your Fedora packages
Last time, we talked about custom kernels in Debian-based systems. This time we go to "the other side" and will also talk about customizations, namely how to customize packages on Fedora systems. For this you are not required to have any prior experience on the matter in order to build packages, but a will to learn and read manual pages or other resources is always welcome.
Our article will focus on Apache as packaged by Fedora, and what we will do is modify some of its build options in order to better fit our needs. After all, Linux and Open Source are all about customization, so why not get exactly what we want? With that being said, let's start with our tutorial. If you still have some questions after reading this article please try our new LinuxCareer Forum.
If you need a package that isn't available in your system's repositories or if you want to change some compile-time options for existing ones, then this tutorial is for you, although for now we will focus on modifying existing rpm packages. Again, no prior experience is needed, but some desire to learn and read (see below for reading material) is desirable. Now, let us start with the basic concepts and what you'll need to install for successfully building rpm packages.
Generically speaking, a package is an archive your package manager (in our case, rpm, which stands for Redhat Package Manager) unpacks and then copies the necessary files to their respective locations as instructed by the spec file (this file is rpm-specific). The main difference that makes rpm offer more than regular archives is that rpm files tell the package manager about the dependencies they have and how to deal with them, plus some other sorts of nifty stuff you won't get by using classic packing systems like .gz, .bz2, .xz, etc.. You can find more information by browsing www.rpm.org and by using the rpm manual page. One must note that rpm is not Fedora-specific : it is also used by other distributions like Redhat, OpenSUSE, Mandriva, Mageia, Meego, but in this article we will focus on Fedora systems.
Finally, you will see references about yum throughout the document : yum is a rpm front-end which has advanced capabilities including dependency checking and up/downgrading, the same way that apt* applications are front-ends to dpkg. These applications are created with the purpose of offering the end-user a better package management experience.
So, let's cut to the chase and fire up a terminal in order to install the necessary packages for compiling our own rpm packages :
# yum groupinstall "Development Tools" # yum install rpmdevtools
It's a good moment to remind you that commands issued with a '#' in front are meant to be used as root, and commands issued with a '$' are meant to be issued as normal user. NEVER use the root account when not needed, especially when compiling. Now, after having the tools installed, we concentrate on the spec file, which controls everything related to rpm building. Our example will be rpm version-agnostic, but in the case of more complicated builds, pay attention to the fact that rpm will have different versions on Fedora as opposed to Redhat and clones, which may lead to problems. If your package is insensitive to differences in rpm versions, the process is basically the same. Our advice is that, for starters, to setup your environment and to get the source rpm for an existing package with
# yum install yum-utils
then setup your tree with
$ cd ~; /usr/bin/rpmdev-setuptree
which will create ~/rpmbuild and all other necessary subfolders (RPMS for binary packages, SRPMS for source packages, BUILD for the build environment and SPECS for spec files) , and then get the source (here, as stated, the example is for Apache):
$ cd ~/rpmbuild/SRPMS/ $ yumdownloader --source httpd
As an example, on my Fedora 16 system I get httpd-2.2.19-4.fc16.src.rpm. Next we'll use yum-builddep which builds the dependencies of the source package (part of the yum-utils package). Note that some packages have quite a few dependencies, so be prepared to have some free space available.
# yum-builddep httpd-$version.src.rpm
Since we want to modify the .spec file, we will first have to install the source rpm that we got earlier with yumdownloader, now that httpd's source dependencies are installed:
$ rpm -ivh httpd-$version.src.rpm
so now we can go on and edit the spec file to meet our needs. $version is the httpd version available in the Fedora repos . The spec file has a pretty simple syntax, it is well-commented and the online documentation is a treasure for every beginner in rpm-land. Nevertheless we will try to give here a few basic considerations about spec files and how to write and understand them.
Since we're assuming no previous package building experience, we suggested an existing package because that means an existing spec file. After you get more confident you can try and write your own. Spec files are divided into sections, each section corresponding to an essential part of building like compiler flags, prerequisites, pre- and post installation operations and so on.Some basic syntax considerations are in order : '#' means a comment, and we recommend you comment your spec files so that you and others will get a good idea about what you are/were trying to do. '%' specifies sections like %build - build flags - or %install - how and where to install the built files - plus there are some keywords which name variables in the spec file : Name, Version, Group, URL are just a few examples that we think are pretty self-explanatory. rpm is a pretty flexible packaging system, so that you can also define conditionals (e.g. if the architecture is i686, do something, if it's x86_64, do something else). This link explains all these naming conventions in great detail. So, we will now go to the ~/rpmbuild folder, edit the spec file then rebuild the package :
$ cd ~/rpmbuild $ vim SPECS/httpd.spec $ rpmbuild -bb SPECS/httpd.spec
Of course, the use of vim as an editor is not mandatory and we sure don't want to get into holy wars. Use whatever editor you're comfortable with to edit the spec file according to your needs. Our recommendation is to never alter settings in the spec file that you do not need or do not know about.
In our httpd.spec file, we will modify the line "/sbin/chkconfig --add httpd" in the %post section (post install section) by commenting it out, because we don't want httpd to be started at boot . More usual modifications, especially when talking about a web server, are adding or removing compile-time options with regard of your specific needs. In our case the Apache manual will explain all options, what they do and the implications. Save the file and continue with rpmbuild. The command syntax is also pretty self-explanatory, since -bb means "build binary", -bs is "build source" and -ba is build all (binary AND source) : so for instance, if you need a .src.rpm, you will use -bs. You will find the binary result of your work in ~/rpmbuild/RPMS/ and may now proceed with the package installation with either
# rpm -Uvh $location_of_package
or, (recommended), with
# yum --nogpgcheck localinstall $location_of_package
If the package is not signed, we use '--nogpgcheck' to prevent yum to check for the package's authenticity, and 'localinstall' is used to install Fedora packages that reside locally (not in a repository) . We said this method is recommended because thusly yum will know about the package and will add it to its internal database. On my system, $location_of_package translates to '~/rpmbuild/RPMS/x86_64/httpd-2.2.19-4.fc16.rpm' . Since I commented out the line about adding httpd at startup, httpd will not start at next boot.
3. Other considerations
What has been discussed here is only rpm building in a nutshell : we haven't discussed the situation when you might have a source (e.g. tar.gz) version of a piece of software that isn't to be found in the repositories and you want to create a .rpm . Also, rpm macros and more advanced subjects are left for another time. Situations differ because needs differ and this tutorial does not compensate for reading and practicing. Use your favorite file manager/editor combination to browse through ~/rpmbuild. Read a few spec files to see and understand what each section represents and what it does. We recommend the use of rpmlint as it is a good program to use on your new spec file in order to check for mistakes, and do not forget to read packaging guidelines if you want to help the project and build/maintain packages. You will find an excellent reference in here which, although it contains more advanced topics, can also help a beginner in building rpms. Good luck.