Chapter 35

Creating Your Own RPM Packages
 

 
 
In this chapter:
 
 
* Organizing the build process
* Learning how to prepare the source code for a RPM Package
* Integrating software into the SuSE Linux Distribution
* Learning to create a Patch-File
* Learning about Spec-Files and how to create them
* Building a sample package
 
 
 
The last chapter explained how to compile and install the source packages included in the SuSE distribution. This is useful when you want to change something in the source code, such as apply a bug fix or change application defaults. But what if you want to create your own RPM because you found some interesting piece of software that is not yet included in the SuSE distribution? The answer is that this is nearly the same procedure as we saw in chapter 34, when we used an SRPM to build a package. The difference is that you have to create the spec and the patch file yourself. Usually it's no big deal to create an RPM package. Sometimes it can be tricky. If you only want to give the new software a test drive, you are probably better of with just compiling and installing it as explained in the documentation that (hopefully) comes with the source. However, if you want to give the package to friends, or you want to use it for other machines running SuSE Linux, the overhead for building the RPM pays off quickly.
NOTE This chapter is not intended to teach you how to compile sources and how to install software on a Linux system. You should have experience with this before and be familiar with make and similar utilities like configure et. al. We will talk about creating an RPM package instead of simply installing the software on a single system. If you have no experience in building software from the source, you may have difficulties following the instructions given here.
 
 
35.1 Roadmap
 

If you decide to build an RPM package for SuSE Linux, you should know about a couple of important points about integrating applications into the SuSE Linux distribution. Integrating software into a system often means more than just creating the binaries from the source and then copy them to a directory where everybody can use it. Most software comes with some kind of configurations file. There is documentation to be installed. There may be something to initialize when the system is booted. Regular scheduled maintenance or clean up scripts may be needed. If there are environment variables needed for this package, they should be included into the users standard environments. We saw in other chapters of this book that SuSE covers all these tasks with custom designed mechanisms. In this chapter we will see how we can use these mechanisms for our new software package.
 
So what tasks are needed in order to create an RPM package?
 

 
* Get the source code
If you don't write the source yourself, you'll probably need to download a tgz file from an FTP server.
* Change the source code or the makefile to adopt it for SuSE Linux
Most software assumes a certain type of file system layout. This may or may not be the layout of the SuSE Linux system you envision the software to run on. In most cases no drastic changes are necessary. Seldomly can you use the source "as-is".
* Create a patch file containing your changes
Remember that in chapter 34 we learned that RPM keeps the original sources and has a patch file reflecting the changes? We're actually about to put this into action.
* Create additional scripts to integrate the package
Again, you may have to write rc-scripts to be executed at boot time to start a new service or create a maintenance script to be scheduled by cron.
* Edit system files to ingrate the package
If you need a rc-script, you may want to use /etc/rc.config to set configuration variables. You also may need entries in /etc/inetd.conf to alert inetd on your new service. Users may need a special environment variable which you may want to include in their standard environment.
All these issues affect system configuration files. You should make these changes and test them. We will see later in this chapter how you can use scripts triggered by RPM during the installation to automate these changes.
* Create a list of all files that belong to the package
RPM needs to have this list. We will see how to create this list and how to mark configuration and documentation files in it.
* Create the spec file
If all of the previously listed tasks are done, we can continue and create a spec-file to automate the whole process of packaging the software.
* Use RPM to build the package
This is the last step. If we have the sources, the patch file, and the spec-file, we can use them to build the package as discussed in chapter 34.
 
 
You see there are quite a few steps to be done. It sounds a lot worse than it actually is. Depending on the kind of software you want to create a package for, you don't have to perform all of these steps. And even if you have to, it's not an impossible task.
 
NOTE No matter how hard you try, there are certain aspects that can't be done with RPM in the SuSE distribution. The most obvious one is that you can't include any package into the SuSE distribution, meaning you can't make it transparent whether the package comes from SuSE or from a third party, in this case from you. YaST uses its own database of packages that are contained in the distribution. SuSE doesn't provide tools to modify this database. Unfortunately, there is no way to include your package into YaST's native package selection mechanism. If you want to see it there, you will have to mail the package to SuSE and hope that they can include it in their next release. The other issue which is more directly related, concerns dependency. Since SuSE doesn't use the dependency features of RPM, you can't rely on them either. YaST has its own dependency database but doesn't provide tools to change it.
 
 
35.2 Preparing the Source Code
 

Just as in the last chapter, we will use an example to walk through the build process. This time we will pick some software that is not yet part of the SuSE distribution, a utility that controls digital cameras based on Sierra Imaging firmware: photopc.
 
To begin, you can download the source from http://www.average.org/digicam. You'll also find more information on this software on the Web site. Obviously, right now our focus is to build the package, not to explore it's functionality.
 
This package doesn't need a lot of customization. The only thing we will add is the automatic creation of a soft link in the /dev directory. PhotoPC uses a serial connection to control the camera. It's default device is /dev/photopc. You can easily guess that this file doesn't exist in SuSE Linux. What we'll do is add a variable to /etc/rc.config [to set the device for] the camera. Then we'll create a script to be called by SuSEconfig, which will read the variable and create the link accordingly. It's pretty simple, and demonstrates how you can integrate new functionality into SuSE's setup structure.
 

35.2.1 Unpacking the Sources
 

Enough of the introduction, let's get started. The first step is to get the sources to the proper place and check if they need any changes in order to build them properly. We assume that you downloaded the source archive to the /tmp directory. We'll start by copying them to /usr/src/packages/SOURCES, and unpacking the archive in /usr/src/packages/BUILD:
 

 
# cd /usr/src/packages/SOURCES/ 
# cp /tmp/photopc-3.01.tar.gz . 
# cd ../BUILD/ 
# tar xzvf ../SOURCES/photopc-3.01.tar.gz 
photopc-3.01/ 
photopc-3.01/a12scan.c 
photopc-3.01/a12scan.h 

 
[... file list skipped ...]
 
photopc-3.01/usleep.c photopc-3.01/usleep.h
 
 
35.2.2 Compiling the Sources
 

Now we have to find out how to build the package. Usually you find a file called README or INSTALL in the source hierarchy, which tells you what to do. In this case it is the README file. The instructions are:
 

 
... 
On Unix, first run "./configure".  Then, type `make' which will 
build the library and executables in the current directory. 
`make install' will install the executables and manual pages. 
`make install.lib' will install the library and the .h file. 
... 
 
 
OK, now let's see if everything works as it's supposed to:
 
 
# cd /usr/src/packages/BUILD/photopc-3.01 
# ./configure --prefix=/usr/local 
creating cache ./config.cache 
checking for gcc... gcc 
checking whether we are using GNU C... yes 

 
[... configure output skipped ...]
 
creating ./config.status creating Makefile creating config.h
 
 
Looks great -- configure had no problems creating the Makefile.
 
NOTE Note that we called configure with the option --prefix=/usr/local. For most packages this the default, but sometimes it isn't and it's a good idea to set it in order to avoid nasty surprises. The --prefix options tells configure where the software should be installed. We learned in chapter 2 that software which is not part of the distribution itself, should go to the /usr/local hierarchy. To ensure that we don't violate the FHS, we use this parameter for configure. In case the package you want to build doesn't support autoconfiguration using configure, you should inspect the Makefile to ensure that the installation path is set accordingly.
 
 
Next is the compilation. Calling make should create the binaries:
 
 
# make 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c eph_read.c 
eph_read.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c eph_iob.c 
eph_iob.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c eph_err.c 
eph_err.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c eph_cmd.c 
eph_cmd.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c eph_io.c 
eph_io.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c eph_open.c 
eph_open.c:2: warning: `rcsid' defined but not used 
/usr/bin/ar r libeph_io.a eph_read.o eph_iob.o eph_err.o eph_cmd.o eph_io.o eph_open.o 
ranlib libeph_io.a 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c photopc.c 
photopc.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c a12scan.c 
a12scan.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c fnames.c 
fnames.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c ctimez.c 
ctimez.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c filetime.c 
filetime.c:2: warning: `rcsid' defined but not used 
gcc  -o photopc photopc.o a12scan.o fnames.o ctimez.o filetime.o -L. -leph_io 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c epinfo.c 
epinfo.c:2: warning: `rcsid' defined but not used 
gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c exifscan.c 
exifscan.c:2: warning: `rcsid' defined but not used 
gcc  -o epinfo epinfo.o a12scan.o exifscan.o fnames.o ctimez.o filetime.o  
 
 
And again, everything looks fine. There are some warnings but nothing that should worry us.
35.2.3 Installing the new Software
 


 
Installation is the next step. Here we need to proceed more carefully, since we need to get a list of all installed files. We need to put that list in the spec file later on. The README file told us to do make install and make install.lib to start the installation:
 

 
# make install 
/usr/bin/ginstall -c -d -m 755 /usr/local/bin 
/usr/bin/ginstall -c -m 755 photopc /usr/local/bin 
/usr/bin/ginstall -c -m 755 epinfo /usr/local/bin 
/usr/bin/ginstall -c -d -m 755 /usr/local/man/man1 
/usr/bin/ginstall -c -m 644 photopc.man /usr/local/man/man1/photopc.1 
/usr/bin/ginstall -c -m 644 epinfo.man /usr/local/man/man1/epinfo.1 

 
# make install.lib /usr/bin/ginstall -c -d -m 755 /usr/local/lib /usr/bin/ginstall -c -d -m 755 /usr/local/include /usr/bin/ginstall -c -m 644 libeph_io.a /usr/local/lib /usr/bin/ginstall -c -m 644 eph_io.h /usr/local/include
 
 
If you look at the output, you see that six files have been installed:
 
 
/usr/local/bin/photopc 
/usr/local/bin/epinfo 
/usr/local/man/man1/photopc.1 
/usr/local/man/man1/epinfo.1 
/usr/local/lib/libeph_io.a 
/usr/local/include/eph_io.h 
 
 
TIP Unlike this example, it's not always easy to figure this out. Some packages have a tremendous number of files to install, but lack a clear output of make install to help sort the files out.
 
In those cases the find utility can help. After you run the make install command, perform a find for all files that have changed in the last five minutes. The list will include some files which don't belong to the package, like log-files and files someone else may have changed at the same time. But it should be obvious which files belong to the new software and which don't. Save this list, we'll refer to it later.
 
35.2.4 Pit Stop #1
 


 
So far we've been really lucky. There was no need to do any customization.
 

TIP What if you had to patch some files to get to this point? Nothing dramatic happens. Just make sure you know which files were changed and that you have copies of those files. Store those copies somewhere outside the of the build tree. We'll come back to them later when we create the patch file.
 
 
At this stage you should have reached the following milestones:
 
* The source package gets installed in its own subdirectory in /usr/src/packages.
* The sources compile without errors.
* Install the binaries, libraries, configuration files, etc. in the /usr/local hierarchy.
* In case there were changes to any files in the source tree, have copies of the changed files at a separate location.
 
 
NOTE One thing we didn't talk about at all, because it's simply too obvious - You should check if the installed binaries actually work. It doesn't interfere with the process of creating the RPM, but it also doesn't make sense to create an RPM for a piece of software that doesn't work. So do your self a favor and take some time to test the installed binaries.
 
 
If all this is true, we can go on to the next step and think about the additional tasks we need to integrate the software into the SuSE setup scheme.
 
35.3 Integration into the SuSE Setup Scheme
 

The photopc utility connects to the digital camera using a serial device. The default device it looks for is /dev/photopc. In earlier discussions, we talked about creating this device in conjunction with a variable in /etc/rc.config by using a script automatically called by SuSEconfig. We have two points to cover:
 

 
* Adding a variable to /etc/rc.config
* Creating a script that reads /etc/rc.config and creates the device according to the specifications in /etc/rc.config
 
 
35.3.1 Adding entries to existing configuration files
 

The first point seems trivial, but it is the more difficult of the two tasks. It is trivial to edit /etc/rc.config manually and add variables to it. We want to do it automatically during the installation of the package. This could still be an easy issue, but we want to make sure that an entry that already exists will be recognized and remain unchanged by the installation procedure. A possible scenario is that someone installed the software, modified the settings, and for whatever reason decided to remove it again.
 

NOTE Entries in /etc/rc.config remain unchanged, even if the software is removed. This is questionable behavior, but it's the SuSE way of doing things. We just have to accept this and work with it.
 
 
So what if the administrator in the scenario we describe decides that he wants to install the package again? He should be able to reuse the configuration he's customized for his system. In our example this configuration is rather trivial, but it's one possibility. There are other packages which use more than one variable, where it is much more desirable not to void the old configuration.
 
SuSE created a tool that merges configuration files: fillup. It's comprised of two files, a basefile and a newfile. Fillup reads both files and checks on whether variables in the new file are not contained in the basefile. New variables are appended to the basefile including comments preceding the variable definition, the variable name, the assignment delimiter, and the variables value.
 
The documentation for fillup is included in the SuSE Linux distribution as info file, GNU's new standard for documentation. So instead of the old standby man, use info fillup to get more information on this tool.
 
So what we have to do is to write the settings we want to add to rc.config into a file and call fillup accordingly. In this case it's just one variable, which we'll call DIGITAL_CAMERA_DEVICE and it should be set to the device the camera it connected to. We create a file to store the setting, photopc.tmpl. We'll add this to /etc/rc.config:
 
 
# 
# Digital Camera Device for PhotoPC Application 
# 
DIGITAL_CAMERA_DEVICE="/dev/ttyS1" 
 
 
The name used here was selected at random. SuSE uses the naming convention packagename.tmpl for its packages, so we've used the same. To see how fillup works, we will call it manually. Later this will be done by the post-install script of the RPM package. To add this variable to /etc/rc.config, all you have to do is go to the directory where you stored the template file and call:
 
 
# fillup /etc/rc.config photopc.tmpl 
 
 
If you look at the end of the file /etc/rc.config, you will see that the new variable and the comment are added, just as specified in the template file. To see if fillup really respects entries which are already in /etc/rc.config, call it again. Try this and you will find out that /etc/rc.config remains unchanged. Even if you move the variable definition around within /etc/rc.config, fillup will find it and not replace it or add a second copy.
 
TIP In our example we used fillup to modify /etc/rc.config. You can use it to modify any configuration file. For example, if you want to make entries to /etc/inetd.conf or /etc/inittab, fillup is a good tool to use. Refer to the info page to learn about options to change the variable/value delimiter, the comment character, and more.
 
 
35.3.2 Extending the SuSE Setup Mechanism
 

The second issue is much easier. It involves a script that uses this entry to create the file. All we need to do is write the script and put in the right place. In chapter 2 we learned that the directory /sbin/conf.d contains scripts which are called by SuSEconfig every time it runs. SuSEconfig takes care of a lot of tasks by itself. When it's finished doing this, it looks in the directory /sbin/conf.d and calls every script that it finds in the file. This mechanism enables it to add functionality to SuSEconfig easily. All you have to do is put a script into /sbin/conf.d. So all we have to do in our script is to read the setting from /etc/rc.config, check if the variable DIGITAL_CAMERA_DEVICE is set, and if so, we create the appropriate link in /dev:
 

 
# 
# /sbin/conf.d/SuSEconfig.photopc 
# 

 
# Read settings from /etc/rc.config test -f $ROOT/etc/rc.config || { echo "No $ROOT/etc/rc.config found." exit 1 } . $ROOT/etc/rc.config
 
# Create link if test -n $DIGITAL_CAMERA_DEVICE ; then echo "Creating link for PhotoPC: $DIGITAL_CAMERA_DEVICE -> /dev/photopc" rm -f $ROOT/dev/photopc ln -sf $DIGITAL_CAMERA_DEVICE $ROOT/dev/photopc fi
 
 
CAUTION Note that we prefixed every path in the script with $ROOT. This is done to keep the script relocatable. Remember when we used a different root directory for the installation of the diskless client in chapter 31? In order to make this feature work reliably, the current installation root is passed to every script involved in the installation. 'If you don't follow this convention, the script may fail in situations like the one discussed in chapter 31.
 
 
To test this, copy the script to /sbin/conf.d and run SuSEconfig. Don't forget to set the executable flag for the script, otherwise it won't be executed:
 
 
# chmod u+x /sbin/conf.d/SuSEconfig.photopc 
 
 
You should see the output of the echo command we inserted in the script during the SuSEconfig execution:
 
 
# SuSEconfig 
Started the SuSE-Configuration Tool. 
Running in full featured mode. 
Reading /etc/rc.config and updating the system... 
Executing /sbin/conf.d/SuSEconfig.gdm... 
Executing /sbin/conf.d/SuSEconfig.groff... 
Executing /sbin/conf.d/SuSEconfig.kdm... 
Executing /sbin/conf.d/SuSEconfig.l2h... 
l2h: Checking installation... Done. 
Executing /sbin/conf.d/SuSEconfig.perl... 
Executing /sbin/conf.d/SuSEconfig.photopc... 
Creating link for PhotoPC: /dev/ttyS1 -> /dev/photopc 
Executing /sbin/conf.d/SuSEconfig.sendmail... 
Executing /sbin/conf.d/SuSEconfig.susehilf.add... 
Executing /sbin/conf.d/SuSEconfig.tetex... 
Processing index files of all manpages... 
Finished. 
 
 
35.3.3 Pit Stop #2
 

At this point we've fully integrated the new software package into the SuSE Linux system. Up till now we've done it manually, which helped us figure out which tasks are needed and to make sure they work. We collected more files to add to the software package. The add-ons to the configuration files (photopc.tmpl in our example), and scripts to expand the functionality of the SuSE tools (this is SuSEconfig.photopc for this example). Now we can go on and automate these steps, so that they are executed during the installation without the need for manual interaction.
 

35.4 Creating the Patch-File
 

Now that we have completed all the preparations, we can continue and create the patch file for the new package. Why do we need a patch file if the software build just fine without any changes? There are two reasons. We created additional files that should be contained in the package. Another way of getting them in there would be to have a separate tgz file, which we unpack from within the spec file. This would work perfectly and is actually a reasonable way to go. The second reason is that we created the patch-file for educational purposes. Since this chapter explains how to build an RPM package, it would be incomplete without explaining the patch mechanism.
 

35.4.1 Creating two trees
 

To create the patch file, we need two directory trees. One represents the original source tree and the other one includes all changes that has been made to this source tree. The patch file will only contain these changes. The obvious intention of the patch file is to be able to restore the revised tree by using the original archive and the patch file.
 
The original source tree is basically the unpacked tgz file. Besides unpacking the file, you must rename it. You can choose whatever new name you'd like. Common practice is to add .orig to the original directory name:
 

 
# cd /usr/src/packages/BUILD 
# tar xzf ../SOURCES/photopc-3.01.tar.gz 
# mv photopc-3.01 photopc-3.01.orig 
 
 
Now we have to unpack the tgz archive again and then apply all changes we need to build the package to this copy of the sources. For this example this means we will create a subdirectory and store the two files we used to integrate the software into the SuSE Linux System in this directory:
 
 
# cd /usr/src/packages/BUILD 
# tar xzf ../SOURCES/photopc-3.01.tar.gz 
# cd  photopc-3.01 
# mkdir SuSE 
# cd SuSE 
# cp /tmp/photopc.tmpl . 
# cp /sbin/conf.d/SuSEconfig.photopc  . 
 
 
The commands we've shown only work for the example illustrated. For any other software there may be additional changes to the actual sources, more files to add, etc. In case, there are two different trees at this point.
 
35.4.2 Finding the difference
 

To create the actual patch file, the command diff is used. In the simplest case, diff compares the contents of two files. If two directories are given as arguments, diff compares corresponding files in both directories, in alphabetical order. Diff never compares the actual contents of a directory as if it were a file. And of course that's what we want to do here- compare the two trees we just created:
 

 
# cd /usr/src/packages/BUILD 
# diff -ruN photopc-3.01 photopc-3.01.orig > ../SOURCES/photopc.diff 
 
 
Issuing the diff command will create the file /usr/src/packages/SOURCES/photopc.diff. If you look at this file, you will see that diff found the additional directory and the two files we copied in there:
 
 
diff -ruN photopc-3.01.orig/SuSE/SuSEconfig.photopc photopc-3.01/SuSE/SuSEconfig 
--- photopc-3.01.orig/SuSE/SuSEconfig.photopc   Wed Dec 31 16:00:00 1969 
+++ photopc-3.01/SuSE/SuSEconfig.photopc        Fri Jul 16 13:34:25 1999 
@@ -0,0 +1,18 @@ 
+# 
+# /sbin/conf.d/SuSEconfig.photopc 
+# 
+ 
+# Read settings from /etc/rc.config 
+test -f $ROOT/etc/rc.config || { 
+        echo "No $ROOT/etc/rc.config found." 
+        exit 1 
+} 
+. $ROOT/etc/rc.config 
+ 
+# Create link 
+if test -n $DIGITAL_CAMERA_DEVICE ; then 
+    echo "Creating link for PhotoPC: $DIGITAL_CAMERA_DEVICE -> /dev/photopc" 
+    rm -f $ROOT/dev/photopc 
+    ln -sf $DIGITAL_CAMERA_DEVICE $ROOT/dev/photopc 
+fi 
+ 
diff -ruN photopc-3.01.orig/SuSE/photopc.tmpl photopc-3.01/SuSE/photopc.tmpl 
--- photopc-3.01.orig/SuSE/photopc.tmpl Wed Dec 31 16:00:00 1969 
+++ photopc-3.01/SuSE/photopc.tmpl      Fri Jul 16 13:34:15 1999 
@@ -0,0 +1,4 @@ 
+# 
+# Digital Camera Device for PhotoPC Application 
+# 
+DIGITAL_CAMERA_DEVICE="/dev/ttyS1" 
 
 
The options we gave to diff mean that it should scan the directories given as argument recursive (-r), create a patch file in unified format (-u) and that new files and directories should be treated as present but empty in the original tree (-N). These options are needed to recreate the status quo using the original source tree as reference later on, when we build the package with RPM.
 
35.4.3 Final Pit Stop
 

At this point we are almost done. We created the patch file containing the differences of our source tree to the original tree. All that's missing is the spec file which contains the instructions on how to build the package.
 

35.5 Creating the Spec-File
 

In chapter 34 we saw that the spec file is the central source of information for building RPM packages. We learned how to use spec files to build binaries from source RPM packages. In this chapter we want to create a source RPM package. This means we will have to create the spec file ourselves.
 

35.5.1 Spec File Sections
 

A spec file contains different sections which reflect the different build stages such as those discussed in chapter 34, plus an additional framework:
 

 
* Preamble
Basic information about the package as a result of calling rpm-qi. It's simply a brief description of the the package, author, copyright, version, release number, etc.
* Prep Section
All steps needed to build the package are defined in this section. This includes unpacking the sources, applying the patch file, running the configure script, and other similar tasks. The prep-section is basically a shell script (bash) which performs these tasks.
* Build Section
Another shell script that performs the package build operations. Usually a single make command that starts the build process.
* Install Section
A shell script which performs the installation. Here you either specify where to put each file, call make install, or both.
* Install and Uninstall and Verify Scripts
The sections prior to these contained scripts that were executed during the build process of the package. However, the scripts in these sections run on the system the package is installed on. You can specify scripts to be executed:
 
* Prior to the package being installed
* After the package has been installed
* Prior to the package being erased
* After the package has been erased
* Or whenever RPM is used to verify the package
 
* Clean Section
You can use this section to specify a script that cleans up after the build. Rarely used, as you can use RPM to do this.
* File List
Here you list all files that should go into the package. This is also the location where you specify which files are documentation and which are configuration files.
 
 
We'll walk through each section and develop the spec file for our example as we move along.
 
35.5.2 The Preamble
 

In general, the preamble consists of one line entries. Every line starts with a tag followed by a colon and the actual information. You can put the lines in any order, but most of them are required, so make sure you don't forget an entry. The preamble for the PhotoPC example is shown below:
 

 
# =========================================================================== 
#                    Spec File for Package PhotoPC 
# =========================================================================== 

 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ # Preamble # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Name: photopc Summary: Tool to Communicate with Digital Cameras Version: 3.01 Release: 0 Copyright: Free Freely distributable Group: bb/graphics/digicam Provides: digicam-download Autoreqprov: yes Source: photopc-3.01.tar.gz Patch: photopc.diff Vendor: Bodo Bauer Distribution: Bodo's Tools Packager: Bodo Bauer <bb@ricochet.net> %description This is a library and a command-line front-end to manipulate digital still cameras based on Fujitsu's chip set and Sierra Imaging firmware. The program is known to work with Agfa, Epson, Olympus, Sanyo and Nikon (at least CoolPix 900, but not CoolPix 600!) cameras.
 
The cameras typically come with software for Windows and for the Mac, but no description of the protocol. With this tool, they are manageable from a Unix box.
 
 
Most tags have obvious meanings, but others are a little obscure, so lets define each tag:
 
 
* Name - The package name
This entry determines what the package will be called. For ease of use, the name should be related to the software you're packaging. You will find the software under this name in the RPM database once it's installed.
* Summary - Short description of the software
A one line description of the software package. It should give an overall idea of what this package is about. A more detailed description will be given later in the preamble.
* Version - Version of the software
This entry contains the version number of the software being packed. This number is used to compute if the software in one package is more recent than the version in another package for upgrade issues. This version also becomes part of the package label.
* Release - Release number of the package
The release number should be increased every time you package the same version of this software. The release number is used to differentiate different builds of the same software version. The release number also is part of the package label.
* Copyright - Copyright Information
The intention of this entry is to hold the package's copyright information, to make is easy to see which packages are freely distributable and which are covered by a proprietary license. However, in most cases, SuSE uses this field to hold the author's name.
* Group - Group information
A slash (/) separated list of strings that is used to set the package in relation to other software packages. The list of groups should become more specific from the left to the right. In the example I chose bb as the most general group and then became more specific in sorting it into graphics and digicam as most specialized relation.
NOTE SuSE has unsorted as entry in almost all their packages. They don't use this feature.
 
* Provides - Virtual package information
To resolve dependencies, RPM supports virtual packages. I.e., your system may require that a mail-reader be installed. This dependency would be resolved if any package that has mail-reader is installed. The thought behind virtual packages is that there may be more than one package providing the same functionality. SuSE doesn't use this feature.
NOTE YaST has it's own dependency database, which is not reflected in the SuSE spec files.
 
* Autoreqprov - Automatic dependency processing
RPM can automatically create a list of provided binaries and shared libraries along with a list of shared libraries which is required by the packages. This tag allows you to turn this feature on (yes) or off (no).
* Source - Name of the source archive
With this tag you specify the tgz file containing the original source tree. In the example we used here, we have a local file as source archive. RPM also supports FTP servers that you may use as a repository for source archives. You could use something like ftp://ftp.server.com/pub/sources/xyz.tgz as the specification of the source file.
You have the flexibility to support multiple source files. To specify additional source files use the tags Source1:, Source2:, and so on.
* Patch - Specification of the patch file
Like the Source tag, this tag is used to specify the patch file for this package. There also can be more than one patch file, specified with the same convention as multiple source files, by adding consecutive numbers to the original tag; Patch1, Patch2, ...
* Vendor - Packager of the software
The name of the person or organization responsible for packaging the software should be specified with this tag.
* Distribution - Name of package group
The name of this tag is somewhat confusing. Contrary to its name, it doesn't denote the Linux distribution this package was built for. The tag should be used to define a group of packages that this particular package is a part of. With a Linux distribution, this tag would indicate the distribution's name. But it also could be your personal tool selection, or a complete set of software that is packaged in a large number of separate RPMs.
* Packager - Package builder
This is the place where your name and e-mail address should be listed. This tag specifies the person who built the package.
* Description - Package description
A detailed description of the package. Unlike the other tags, the description can span more than one line. This description should give a short, but not too brief overview of the software's purpose.
 
 
These are the tags often found in the preamble. There are more tags available. For example, you can specify an icon for the package which graphical RPM tools may use or a URL to the software's home page. Refer to the RPM documentation for a full list of all package tags. In general the tags I've described should be sufficient to build most packages. Most of the tags contain information that are meant to provide information about the packaged software for users who are about to install the package or want to find out more about what they already have on their system. Only the tags listed are actually needed for the automated package build.
 
35.5.3 The Prep Section
 

The prep section doesn't contain any information meant for "human consumption". It is entirely focused on automating the preparation stage of the build process. The line %prep starts the prep-section. After that, shell commands which perform the preparation are given. In chapter 34 we saw that this includes unpacking the archive, applying the patch file, and probably running a configure script:
 

 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
# Prep-Section 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
%prep 
%setup -n photopc-3.01 
%patch -p1 
./configure --prefix=/usr/local 
 
 
You see the use of two macros in the prep-section above -- %setup and %patch. In addition to shell commands, these two macros are provided by RPM to make life easier for the package builder.
 
 The 'setup' Macro
 

To simplify the unpacking of the source archive, the %setup macro combines a bunch of shell commands into one call. The line
 

 
%setup -n photopc-3.01 
 
 
triggers the following tasks:
 
* Reverts to the BUILD directory
* Removes the old build tree of the package, if there is one
* Decompresses and unpacks the source archive
* Becomes the source tree
* Sets owner and group of all files to root
* Sets sane permissions for all files in the source tree
 
 
The directory name of the source tree inside the BUILD directory is given with the -n parameter. It defaults to the name of the source archive, after the tgz extension has been stripped. Another frequently used option is -a number. You use this to set up additional source files. For example, if you specified a second source file using the Source1: tag in the preamble, you would use %setup -a1 to unpack this source tree.
 
There are more options to this macro which are often not needed, but sometimes very useful. If you have special issues, refer to the RPM documentation to get a description of those options.
 
 The 'patch' Macro
 

As you may have guessed, this macro is used to apply patch files to the source tree. There are two important options for this macro. The -p number options used to strip the smallest prefix containing number leading slashes from each file name found in the patch file. A sequence of one or more adjacent slashes is counted as a single slash. This controls how file names found in the patch file are treated.
 
The other option worth mentioning, -P number, has the same function as -a to %setup, it tells %patch which patch-file to use. A patch-file listed as Patch1: in the preamble will be applied using %patch -P 1.
 
There are more options to this macro too, which again can be found in the RPM documentation.
 

35.5.4 The Build Section
 

After preparing the source tree, it's time to compile the sources. This is controlled by the build-section of the spec-file. This section begins with the keyword %build and contains shell command to initiate the build process. In most cases a simple make will do the job, just as it is the case in our example:
 

 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
# Build-Section 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
%build 
make 
 
 
35.5.5 The Install Section
 

All commands needed to install the files that belong to this package belong to this section. Often a make install is all you need. But if you have additional documentation or custom created files to install you will need to do some additional work here, like we had to do for our example package:
 

 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
# Install-Section 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
%install 
make install 
# copy additional docs to /usr/doc/packages/photopc 
mkdir -p /usr/doc/packages/photopc 
cp README protocol.htm readme.dos /usr/doc/packages/photopc 

 
# check if this is a SuSE Linux system and install the custom parts if test -d /sbin/conf.d ; then cp SuSE/SuSEconfig.photopc /sbin/conf.d if test -d /var/adm/fillup-templates ; then cp SuSE/photopc.tmpl /var/adm/fillup-templates fi else echo "Not a SuSE Linux system?" fi
 
 
You see the first command is make install which runs the install routine of the package itself. Then the documentation files included in the sources are copied to /usr/doc/packages/photopc.
 
NOTE SuSE's convention is to install README files, license information, and pretty much any other kind of documentation to the directory hierarchy /usr/doc/packages. If you look into this directory, you'll find a separate subdirectory for each installed package containing these files. It's a good habit to follow this convention -- create a new directory with the package name and copy all interesting files to it.
 
 
The last step in the install-section in this example is copying the files we created to integrate the package into the SuSE setup scheme to their desired locations. You see we do some simple checks to make sure that the target system is in fact a SuSE Linux installation before we copy the files.
35.5.6 Scripts
 


 
All tasks listed in the prep-, build-, and install-sections are executed during the building of the actual package. As mentioned in the overview section at the beginning of this chapter, we have the ability to specify scripts to be executed when the package is installed or erased too. RPM offers four possibilities to execute command during the installation:
 

 
* pre-install-script: %pre
Commands following the %pre keyword are executed before the package is installed.
* post-install-script: %post
Commands following the %post keyword are executed after the package is installed.
* pre-uninstall-script: %preun
Commands following the %preun keyword are executed before the package is erased.
* post-uninstall-script: %postun
Commands following the %postun keyword are executed after the package is erased.
 
 
Looking at this list, it becomes obvious that we need a post-install-script to call the fillup utility to modify /etc/rc.config when the package is installed:
 
 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
# Post-Install-Script 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
%post 
if test -f /etc/rc.config -a -x /bin/fillup ; then 
   /bin/fillup /etc/rc.config /var/adm/fillup-templates/photopc.tmpl 
   echo "**" 
   echo "** Please run SuSEconfig to create the camera device" 
   echo "**" 
else 
   echo "Not a SuSE Linux system?" 
fi 
 
 
The script does exactly what we have done manually when we assembled the package contents. The only thing I added is a simple check that verifies if the file /etc/rc.config and the fillup utility are present.
 
We don't need any other script for our PhotoPC example. If you run into a situation where it would be handy to have a pre-install or, pre/post-uninstall script, just create one as shown here, but replace %pre with the appropriate keyword from the list given above.
 
35.5.7 The File List
 

Last but not least in the spec file is the list of all files contained in the package. Only the files listed here will end up in the RPM package, so be very careful that you don't miss anything when you compile this list, or it'll be missing in the resulting package.
 
The file is also the place where you mark configuration and documentation files. To mark a file as documentation, place the keyword %doc in front of the file path and name. The keyword %config is used to mark configuration files. The list for the PhotoPC example looks like this:
 

 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
# File-List 
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
%files 

 
# binaries /usr/local/bin/photopc /usr/local/bin/epinfo
 
# library /usr/local/lib/libeph_io.a
 
# include file /usr/local/include/eph_io.h
 
# man pages %doc /usr/local/man/man1/photopc.1 %doc /usr/local/man/man1/epinfo.1
 
# docu %doc /usr/doc/packages/photopc
 
# config files %config /var/adm/fillup-templates/photopc.tmpl %config /sbin/conf.d/SuSEconfig.photopc
 
 
TIP If you list a directory name, as was done for /usr/doc/packages/photopc, then the whole file tree, starting with this directory, will become part of the package. You can use this feature to avoid listing hundreds of files separately if they all part of the same hierarchy.
 
CAUTION But be sure not to include any file in the list that is already part of another package. RPM will report a conflict at installation time and refuse to install the package if there are overlapping between packages.
 
 
35.5.8 The finish line
 

If you take the single section and put them in a file in the order shown, then you have the spec file for our PhotoPC package. This was the last piece and makes the example complete. We have the source package, the patch-file, and finally the spec-file. That's all we need to build the RPM and the SRPM packages. The actual build process works exactly as discussed in chapter34 for source packages coming from the SuSE CDs.
 

TIP To make your life easier, you can use the spec-file shown, or any spec file from the SuSE SRPMs as a template for your own package. It's always easier to modify a working example than to create one from scratch.
 
 
The process of creating a spec file is usually done by multiple passes of trial and error. Having a working version on the first try is the exception. Usually it takes some time until you are satisfied with the results and everything works as you intended.
 
35.6 Build the RPM and SRPM packages
 

To make the example complete, we'll build the package by calling rpm -ba photopc.spec:
 

 
# rpm -ba photopc.spec 
Executing: %prep 
+ umask 022 
+ cd /usr/src/packages/BUILD 
+ cd /usr/src/packages/BUILD 
+ rm -rf photopc-3.01 
+ /bin/gzip -dc /usr/src/packages/SOURCES/photopc-3.01.tar.gz 
+ tar -xvvf - 
drwxr-xr-x crosser/group     0 1999-04-28 01:45 photopc-3.01/ 
-rw-r--r-- crosser/group  2941 1999-04-28 01:44 photopc-3.01/a12scan.c 
-rw-r--r-- crosser/group  1371 1999-04-28 01:44 photopc-3.01/a12scan.h 
-rw-r--r-- crosser/group 16024 1999-04-28 01:44 photopc-3.01/comio.c 
-rw-r--r-- crosser/group  1244 1999-04-28 01:44 photopc-3.01/comio.h 

 
[... output skipped ...]
 
-rw-r--r-- crosser/group 12833 1999-04-28 01:44 photopc-3.01/usage.htm -rw-r--r-- crosser/group 6825 1999-04-28 01:44 photopc-3.01/usleep.c -rw-r--r-- crosser/group 947 1999-04-28 01:44 photopc-3.01/usleep.h + STATUS=0 + '[' 0 -ne 0 ']' + cd photopc-3.01 + chown -R root . + chgrp -R root . + chmod -R a+rX,g-w,o-w . + echo 'Patch #0:' Patch #0: + patch -p1 -s + ./configure --prefix=/usr/local creating cache ./config.cache checking for gcc... gcc
 
[... output skipped ...]
 
creating Makefile creating config.h + exit 0 Executing: %build + umask 022 + cd /usr/src/packages/BUILD + cd photopc-3.01 + make gcc -g -O -Wall -DHAVE_CONFIG_H -DUNIX -c eph_read.c
 
[... output skipped ...]
 
gcc -o epinfo epinfo.o a12scan.o exifscan.o fnames.o ctimez.o filetime.o + exit 0 Executing: %install + umask 022 + cd /usr/src/packages/BUILD + cd photopc-3.01 + make install /usr/bin/ginstall -c -d -m 755 /usr/local/bin
 
[... output skipped ...]
 
/usr/bin/ginstall -c -m 644 epinfo.man /usr/local/man/man1/epinfo.1 + mkdir -p /usr/doc/packages/photopc + cp README protocol.htm readme.dos /usr/doc/packages/photopc + test -d /sbin/conf.d + cp SuSE/SuSEconfig.photopc /sbin/conf.d + test -d /var/adm/fillup-templates + cp SuSE/photopc.tmpl /var/adm/fillup-templates + exit 0 Processing files: photopc Finding provides... Finding requires... Provides: digicam-download Prereqs: /bin/sh Requires: ld-linux.so.2 libc.so.6 Wrote: /usr/src/packages/SRPMS/photopc-3.01-0.src.rpm Wrote: /usr/src/packages/RPMS/i386/photopc-3.01-0.i386.rpm
 
 
Nothing new here. We discussed the build process in chapter 34. The listing above shows how all the steps discussed there are performed for the new software package. As a result we get two files, the RPM and the SRPM package. You can use the RPM to install it on any SuSE Linux system. It should even work on non-SuSE systems, because in the spec file we made sure that we checked that the SuSE mechanisms we used are actually present.
 
Save the SRPM, since you may need it when a new version of the software is released.
 
TIP In this case you probably don't have to do anything but to change the Source: and Version: tag of the spec-file to build the new release. This is the greatest advantage for using patch files. You don't have to make your changes over and over again. Simply use the patch file to apply them to the new version.
 
 
 
Summary:
  In this chapter we used an example to see the steps needed to create a RPM package for the SuSE Linux distribution. We broke down the build process into single steps and performed these steps one by one until we had the desired RPMs.
 
We started by manually manually through the build process and carefully noted all modifications needed to adopt the software to the SuSE Linux system. These modifications were collected in a patch file which was used to automate the build process. We created a spec-file to control this process and finally ended up with an RPM and a SRPM package ready to install on any SuSE Linux system.
 
--
Back Up Contents Next
--

Copyright (c) 1999 by Terrehon Bowden and Bodo Bauer
To contact the author please sent mail to bb@bb-zone.com