rpmbuild -ba this_should_be_easier.spec

Anybody who has installed a application that has 30-50 dependencies with yum will say it was as easy as saying yes, trying to install the same without yum and just the rpm files is a more tedious of a task but still easy, and if you installed the same from source your in for a couple days of work. repositorys and rpms make life easy and also add definitions of the files being installed, so if you ever need to uninstall it is as easy as “rpm -e $programName”. I’m going to run you through some basics on how to create a rpm and then how to create a yum repository, this is great for those like me who need to have a common library of software on all my servers.

Creating a rpm

First of let me say I’m a Redhat guy so I’m not going to say this won’t work on a none Redhat operating system but I will say i’ve never tried.

So first thing is first you need to install rpm-build, you can do this 1 of 4 ways,

  1. yum install rpm-build (if you got yum)
  2. up2date rpm-build (if you got up2date)
  3. download it from your distros website,
  4. install it from source

Ok now that we can use the command “rpmbuild” your set, no it’s time to decide what we are going to create a package for, I’m going to build one of MING, which is a cool little library to build Flash’s swfs with. Ok so first of download the latest source of the program you want to create a rpm for.

Now would be a good time to explain the rpm build directory structure

    • Is where rpmbuild will try to compile, and make your program
  • RPMS
    • Is where rpmbuild will create your brand new rpms
    • Is where you put all your source tarballs
    • Is where you place your spec files that describe your rpm
    • Is where rpmbuild will place your new SRPMS

Now grab a copy of the latest source.

Time for the spec file.

Whats a spec file you might ask? Its the brains behind your rpm, it defines your package, the file in it and how to get everything to work right. Here is my spec file for Ming, below I’ll define each section in more detail.

Summary: SWF output library
Name: ming
Version: 0.3.0
Release: 1
License: LGPL
Group: System Environment/Libraries
URL: http://www.libming.net/

Source: http://easynews.dl.sourceforge.net/sourceforge/ming/%{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}
BuildRequires: zlib-devel, perl, bison, flex, libpng-devel, libungif-devel

Ming is a C library for generating SWF (”Flash”) format movies,
plus a set of wrappers for using the library from C++ and popular
scripting languages like PHP, Perl, Python, and Ruby.

%package devel
Summary: Header files, libraries and development documentation for %{name}.
Group: Development/Libraries
Requires: %{name} = %{version}-%{release}

%description devel
This package contains the header files, static libraries and development
documentation for %{name}. If you like to develop programs using %{name},
you will need to install %{name}-devel.

%setup -q

./configure \
–bindir=%{buildroot}%{_bindir} \
–libdir=%{buildroot}%{_libdir} \
–mandir=%{buildroot}%{_mandir} \

make install

rm -rf %{buildroot}

%defattr(-, root, root, 0755)

%files devel
%defattr(-, root, root, 0755)

Now for the explanation

First off the header, its pretty much the information about what this package contains, needs, and replaces. Here is a quick list of header vars.

  • Summary
    • Is a one line and one line only quick description of your package
  • Name
    • The package name. try to keep this the actually programs name don’t do seans-ming or anything like that just do ming.
  • Version
    • The Program Version
  • Release
    • The RPM Release every time you make a edit to a rpm that is already installed on a system, Just add to this number, then when the client uses yum update, it will now this is a newer version than the one it currently has installed
  • License aka Copyright
    • Some rpmbuild programs like Copyright some like License. Basically just put the copyright information or the license.
  • Group
    • The type of program or files that are in your package, their is a real list here, no just making up some names.
    • You check the list usually in /usr/share/doc/rpm-*/GROUPS
    • Here is my list for Red Hat Enterprise 4
      • Amusements/Games
      • Amusements/Graphics
      • Applications/Archiving
      • Applications/Communications
      • Applications/Databases
      • Applications/Editors
      • Applications/Emulators
      • Applications/Engineering
      • Applications/File
      • Applications/Internet
      • Applications/Multimedia
      • Applications/Productivity
      • Applications/Publishing
      • Applications/System
      • Applications/Text
      • Development/Debuggers
      • Development/Languages
      • Development/Libraries
      • Development/System
      • Development/Tools
      • Documentation
      • System Environment/Base
      • System Environment/Daemons
      • System Environment/Kernel
      • System Environment/Libraries
      • System Environment/Shells
      • User Interface/Desktops
      • User Interface/X
      • User Interface/X Hardware Support
  • Vendor
    • The company/group/individuals who created the program/scripts your packaging
  • Packager
    • You, yourself, or what you like to call yourself, and usually a email address
  • URL
    • The Creators URL. not the packager, but the actually company/group/individuals page about the program your packaging.
  • Source, Source0, Source1, SourceN
    • The download location of your sources if you have multiple source use a postfixed number starting with zero. so your first would be Source0 your second Source1.
  • BuildRoot
    • A temporary path to test install your package, usually people use %{_tmppath}/%{name}-%{version}-%{release} but this really can be anywhere, rpmbuild will automatically create this, so no need to make sure the directory really exists or not.
  • BuildRequires
    • The rpms required to build this rpm, and you may not need these on the actual installed machine. This list can be seperated by spaces or you can drop it down to multiple lines. You can also specify the version (if necessary) like so packageName = version or packageName > version
  • Requires
    • What is a prerequisite of this package for instance for php-mysql, which is the mysql module for php, you would need first php and mysql. This has the same syntax as BuildRequires.
  • Obsoletes
    • Normally, when creating a updated version you’ll just change the version number but if for instance your creating a rpm for php5, it would obsolete phpfi.
  • Provides
    • This is usefull for stating the fact that this package provides also another package, perhaps one that was obsoleted by this package.

All done with the header, now for the sections…

  • %description
    • A good sized description of your package, this can be as many lines as you like. for use with sub-packages just add the name after like below and throw in your description just like you normally would

%description devel
This is my description for %{name}-devel.
If you like to develop programs using %{name},
you will need to install %{name}-devel.

  • %package
    • Used for sub-packages, like in this case devel, the name will automatically be ming-devel unless I do something like below then it would just be devel-ming.

%package -n devel-ming

  • %prep
    • Its the prep sections focus to clean up previous build and to create a new build enviroment. which means remove the old junk and get ready everything ready to go. this includes but not limited to remove the old build-root, create any directories you might need, and uncompress your source into the new build-root
  • %build
    • The build is where the compiling happens. you do your ./configure and your make, when you do your configure, check the possible options you send to it with ./configure –help then add your new ones like in my case I changed the bindir, libdir, mandir, and the includedir. sometime you can’t do this most times you can, but if you can’t another way to get things to work is shoot a flag into the make, just `less Makefile` and look for which vars you need to change then go like this

make VarName=NewValue NextVar=nextValue

  • %install
    • The Install section is where everything gets moved to in proper location, this again can be as easy as make install or as hard as using the install command for everyfile needed.
  • %clean
    • If you want you can use this section to split up your %prep section and have the %prep section just set up your new build enviroment and have this one do the cleanup from the previous build.
  • %files
    • This is where you list all the files that are install from this package, every one. You can use wild cards (*), And you can list folder. Any folder thats list will be completely remove so make sure that only your package has contents in that folder before listing it. for sub-packages you need to do %files devel and list all the files in that package. How do you get the files list you might ask… here is a couple of ways, my personal favorite is the last one.
      • Some people have attempted to use a modified version of install that logs the name of every file it installs. But not every makefile uses install, or if it does, uses it sporadically
      • Read the makefile to see what files it installs, verify this against the files installed on the build system, and create the list
      • And last but not least grab the list of files before you install, and after you install then do a diff, and weed out the proc and tmp files that hopped in, here is a example, but make sure you weed out the proc files.

find /* > files.before
make install
find /* > files.after
diff files.before files.after > files

Some extras

you don’t always need these ones but sometimes they come in handy

  • %pre
    • The %pre script executes just before the package is to be installed. It is the rare package that requires anything to be done prior to installation; none of the 350 packages that comprise Red Hat Linux Linux 4.0 make use of it.
  • %post
    • The %post script executes after the package has been installed. One of the most popular reasons a %post script is needed is to run ldconfig to update the list of available shared libraries after a new one has been installed. Of course, other functions can be performed in a %post script. For example, packages that install shells use the %post script to add the shell name to /etc/shells.
    • If a package uses a %post script to perform some function, quite often it will include a %postun script that performs the inverse of the %post script, after the package has been removed.
  • %preun
    • If there’s a time when your package needs to have one last look around before the user erases it, the place to do it is in the %preun script. Anything that a package needs to do immediately prior to RPM taking any action to erase the package, can be done here.
  • %postun
    • The %postun script executes after the package has been removed. It is the last chance for a package to clean up after itself. Quite often, %postun scripts are used to run ldconfig to remove newly erased shared libraries from ld.so.cache.
  • %verifyscript
    • The %verifyscript executes whenever the installed package is verified by RPM’s verification command. The contents of this script is entirely up to the package builder, but in general the script should do whatever is necessary to verify the package’s proper installation. Since RPM automatically verifies the existence of a package’s files, along with other file attributes, the %verifyscript should concentrate on different aspects of the package’s installation. For example, the script may ensure that certain configuration files contain the proper information for the package being verified:

Time to build

The spec file is really were the work is involved, building is more of just a test of how good your spec is.

rpmbuild -ba yourspecfile.spec

It will either work and state the rpms written at the end or will error out, getting it to create the rpms is a huge success but your not out of the fire yet, you still need to test your rpms out. By the way a source rpm or SRPM will be created in this process, this rpm contains your sources, patches, and your spec file. Ok, so to test out your new rpm, use a clean machine, don’t use the same box you created it on, its tainted because of the testing, pre-building and all that stuff. So find another box, running the same distro and cpu arch as your machine, throw it on and test it out. If it don’t your in for more work if it does, then great. You can throw it in your yum repository, which I’ll be writing about how to do in my next post.

And thats it, well the basics at least…

I would suggest doing a simple/small package first then work your way up, good luck…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s