Enough to be Dangerous Powerful Information Technology

12Jan/123

Building Custom RPM Packages in CentOS

While I'm sure there are plenty of *nix hackers out there who like building open source packages from source, I'm not one of them. I'm a fan of using a package manager, and since CentOS is my server distro of choice, RPM it is. While CentOS (well... RHEL) has a vast array of packages available and EPEL adds even more, not every package under the sun that you might want to use is available or as up to date as you'd like.

Guru Labs has an excellent write up on creating RPMs. I can't recommend it enough. But, in the "Enough to be Dangerous" spirit, here's a brief guide to how I create custom RPM packages.

Create your environment

While I have a nasty habit of doing a lot of things I shouldn't do as root, creating RPM packages isn't one of them. One of the problems I have with the whole untar, configure, make, make install as root process is that you don't really know where things are being put. Building RPMs as a regular user should prevent any unintentional intrusions into your nice, stable, OS.

I start by creating a bin directory in my home directory. Then I put in a file named cleanrpm with commands from the Guru Labs guide.

cd ~
mkdir bin
vim cleanrpm

Here is the contents of my file.

rm -rf ~/rpmbuild rm -rf ~/.rpmmacros mkdir -p ~/rpmbuild/{BUILD,RPMS,S{OURCE,PEC,RPM}S} mkdir ~/rpmbuild/RPMS/{i386,i586,i686} echo "%_topdir $HOME/rpmbuild" > ~/.rpmmacros echo "%debug_package %{nil}" >> ~/.rpmmacros

Make your script executable and run it to create your directory structure.

chmod +x ~/bin/cleanrpm

You'll also need to install the Development Tools package group. Yes, you're going to compile some code here, but it will be done in a controlled environment.

sudo yum groupinstall "Development Tools"

Going to the source

Where you go from here depends on what kind of resources you can find for the package you want to work on. The best case scenario is to find a source RPM package. Often, you'll find the package you want, but its source RPM is intended for Fedora or an older version of RHEL. Sometimes these packages will work fine if you just rebuild the RPM. Things will usually work best if you use a source RPM package intended to something close to your target. Packages for RHEL or Fedora will work better on CentOS than ones for SuSE or Mandriva.

I'm sure there's an easier way to do this, but this is how I do it.  Install the source RPM in the environment you just set up - not as root.

rpm -ivh somepackage.1.2.3.src.rpm

This will, at the very least, put a .spec file into ~/rpmbuild/SPECS. It will most likely put a tarball into ~/rpmbuild/SOURCES and possibly some patch files.

Often, from here it's simply a matter of building the package.

rpmbuild -ba ~/rpmbuild/SPECS/packagename.spec

If you go through all the compile process and such and end up with an exit status of 0 and you see that some RPM files got written, you're probably golden. If you get errors, you might have to edit some things in the .spec file or take more drastic steps. See the Guru Labs guide mentioned above, or Google it if you're feeling lucky.

The next best senario is that the source tarball you download contains a .spec file. Typically, from here its a matter of copying the .spec file in the ~/rpmbuild/SPECS directory, and the source tarball into ~/rpmbuild/SOURCES. Once again try to build the package with the rpmbuild command. Again, if you run into errors, refer to Google or invest the time to read and understand the Guru Labs guide.

The last scenario I'll mention is when you're faced with no source RPM and no .spec file. Sadly, there is no easy path from here. You'll simply have to invest the time in doing the deep dive into RPM creation. The oft mentioned Guru Labs guide has an example of this very scenario. If I reach this point I tend to look for another solution to the problem I'm trying to solve because, well, my time is just too valuable for this. (That should read as, "I'm lazy.")

Enough talk. Let's do this thing!

Recently, I found myself with a need for a package named sendpage. I couldn't find a ready-made package for it, but was delighted to find that the source tarball contained a .spec file. The README mentions that it's intended for SuSE, but we're going to give it a shot.

I already have my RPM creation environment ready so, I'll download the latest stable version of the package.

wget http://sendpage.org/download/sendpage-1.000003.tar.gz

I'll untar the package...

tar -xzvf sendpage-1.000003.tar.gz

And, I'll copy the .spec file and the source tarball into the right places.

cp sendpage-1.000003/sendpage.spec ~/rpmbuild/SPECS
cp sendpage-1.000003.tar.gz ~/rpmbuild/SOURCES

And, throwing caution to the wind, let's try and build this sucker.

rpmbuild -ba ~/rpmbuild/SPECS/sendpage.spec

OK, we've run into a snag. It looks like the .spec file is referencing a version number different from what we've got.

error: File /home/dstoliker/rpmbuild/SOURCES/sendpage-1.tar.gz: No such file or directory

Don't panic! Let's fire up our trusty text editor and see if we can't coax it into working. It looks like all we need to do is update the version number of the package to match the filename. Change this line:

%define pkgversion 1.000003

OK, give it another try. On my particular system, RPM complained that it needed some additional packages installed. So... install them.

sudo yum install perl-Device-SerialPort perl-Net-SNPP perl-MailTools

On my system, I ran into one more snag - I was missing a needed package that wasn't listed in the .spec file's "Requires" list, so I added it.

Requires: perl perl-Device-SerialPort >= 1.0.2 perl-Net-SNPP perl-MailTools perl-DBI

If you already have the package installed, you won't get this error. On my third attempt, I was met with success! We could be done now, but one last thing to do now that we have a successful build would be to update the changelog on the .spec file. Edit your .spec file one more time and add something like this to the top of the list following the %changelog section:

* Thu Jan 12 2012 me@mydomain.blah
- Updated version to match source file
- Added perl-DBI to Required installed package list

This will help you keep track of when you last modified the file, and also the changes you had to make to get it working.

OK, build it one more time.

rpmbuild -ba ~/rpmbuild/SPECS/sendpage.spec

You'll find the RPM(s) in the ~/rpmbuild/RPMS directory structure - depending on the architecture you're using. This particular package (since it's written in Perl) is in the noarch subdirectory. Now, you can copy your package somewhere for safe keeping and install it.

sudo rpm -Uvh sendpage-1.0.0-1.noarch.rpm

If you'd like to see what files got put where, use this handy command:

rpm -qil sendpage

Be sure to tuck a copy of the source RPM away as well. You'll find it in the ~/rpmbuild/SRPMS directory. It will contain not only your modified .spec file, but the all the source files that go with it. If you need to make changes or updates, you won't have to start from scratch.

When you're all done with this packaging adventure, clean up after yourself by running the cleanrpm script you created earlier.

That's it! You've built a custom RPM package for your system. Hopefully this inspires you to take on more daunting packages - like something not written in Perl. Happy Packaging!

Comments (3) Trackbacks (0)
  1. you have a typo in the rpmbuild instructions. you wrote:

    rpmbuild -ba ~/rpmbuild/sendpage.spec

    while it should be:

    rpmbuild -ba ~/rpmbuild/SPECS/sendpage.spec

  2. Right you are. Updated. Thanks for catching that!

  3. I have a java application it does not have any make file or rpm we are using it as .zip file. when am going to install it i just unzip the file and “./bin/catalina.sh run” for running the application. I need to package it down.

    Can you please help me to creating spec file. and what are the requirement to create……rpm


Leave a comment

(required)

No trackbacks yet.