Showing posts with label spec file. Show all posts
Showing posts with label spec file. Show all posts

Monday, April 14, 2008

Converting Solaris Pkg's Into RPM's on Linux

Greetings,

Today, we're going to wrap up our series of posts on rpm/pkg mixing and matching, as this is about the last thing that's, technically, really worthwhile doing (I think). So far we've created the following scripts based on Linux RPM and/or Solaris Unix pkg dissection, translation and derivation:

How to unpack Solaris datastream packages without using Sun's pkg tools

How to build pkg's using spec files, like in Linux, with pkg-build

How to create RPM's from already installed RPM packages

How to create Solaris datastream pkg's from already installed pkg's

How to convert Linux RPM's into Solaris datastream pkg's

How to build Linux RPM's part 1- Initial points

How to build Linux RPM's part 2 - Starting your spec file

How to build Linux RPM's part 3 - Finalizing the spec file and building the RPM

How to build your own Solaris datastream pkg's quickly

How to build your own Solaris datastream pkg's (more theory than practice)


And, now, whether or not it will ever be practical, we've put together a script to convert Solaris pkg's to RPM's on a Linux system. If nothing else, it rounds everything out :)

The script is easy to run, and only requires one argument of the pkg file that you'll be converting. For instance, to convert the Solaris 9 m4 pkg from SunFreeware.com, you'd just type this (after unzipping the package with gunzip):

host # ./pkg2rpm m4-1.4.10-sol9-sparc-local

One special note about this Perl script: When the pkg gets converted to an RPM, it's done so with the files (listed under the "%files" specification in the "spec file") saved in the RPM with the full path to the temporary build root. This is done because "%files" won't accept relative pathnames and also won't allow you to add files that don't exist (if you, say, populate "%files" with %{prefix}/bin/whatever, etc). Instead, the "Prefix:" value is set to the "BASEDIR" value in the pkg file (e.g. /usr/local), but the "%files" listed are in their actual location during the build (otherwise we'd be forced to overwrite good Linux binaries with potentially unexecutable Solaris binaries just to build the RPM). Therefore, you'll need to install the newly created RPM with the "--relocate" switch.

So, in our example, assuming we ran the above command from "/home/user" (with the pkg file being in that directory), we would want to install the resulting RPM file by first determining where it's supposed to be relocated and then running the "rpm" command, like so:

host # ls
m4-1.4.10-sol9-sparc-local m4-1.4.10-1.x86_64.rpm
host # rpm -qif m4-1.4.10-1.x86_64.rpm|grep -i reloc
Name : m4-1.4.10-1 Relocations: /usr/local
<--- The "Relocations:" specification is where we'll be relocating "to."
host # rpm -qlf m4-1.4.10-1|head -1 <--- The trunk of this output shows us where we will be relocating "from." In this case "/home/user/SMCm4"
/home/user/SMCm4/bin/m4

Now we know where we're relocating "from" and "to," so we're ready to install (Note that you can install this RPM in your home directory, or the build directory, if you want to. The only downside is the inconvenience ;)

host # rpm --force --nodeps --relocate=/home/user/SMCm4=/usr/local -ivh m4-1.4.10-1.x86_64.rpm
Preparing... ########################################### [100%]
1:m4 ########################################### [100%]


Now, all we have to do is a quick verify and we should see that we're all set:

host # rpm -q m4-1.4.10-1
m4-1.4.10-1
host # rpm -ql m4-1.4.10-1.x86_64.rpm|head -5
/usr/local/bin/m4
/usr/local/doc/m4/AUTHORS
/usr/local/doc/m4/BACKLOG
/usr/local/doc/m4/COPYING
/usr/local/doc/m4/ChangeLog


Here's hoping we've covered every useful angle of Solaris Unix datastream pkg to Linux RPM conversion and manipulation that we possibly can. At least for the here and now ;)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

Cheers,

#!/usr/bin/perl

#
# pkg2rpm - convert Solaris datastream pkg files to RPM's for Linux
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if ( $#ARGV != 0 ) {
print "Usage: $0 pkg_file\n";
exit(1);
}

$pkg_name = $ARGV[0];

chomp($simple_header_check=`grep -i "package datastream" $pkg_name >/dev/null 2>&1;echo \$?`);

if ( $simple_header_check != 0 ) {
print "This doesn't appear to be a valid SVR4 DataStream pkg file. Exiting...\n";
exit;
}

open(PKG, "<$pkg_name");
@pkg_file = <PKG>;
close(PKG);

$header_end = 0;
$cpio_start = 0;
open (P_HEADERS, ">$pkg_name.headers");
foreach $line (@pkg_file) {
if ( $header_end == 0 && $line =~ /TRAILER/ && $line =~ /pkginfo/ ) {
print P_HEADERS $line;
$header_end = 1;
} elsif ( $header_end == 1 && $line =~ /pkginfo/ ) {
print P_HEADERS $line;
close(P_HEADERS);
$cpio_start = 1;
open(P_CPIO, ">$pkg_name.cpio");
} elsif ( $cpio_start == 0 ) {
print P_HEADERS $line;
} elsif ( $cpio_start == 1 ) {
print P_CPIO $line;
} else {
print STDERR "WTF?\n";
}
}
close(P_CPIO);

open(P_HEADERS, "<$pkg_name.headers");
@p_headers = <P_HEADERS>;
close(P_HEADERS);

$output_dir = 0;
$pkginfo_start = 0;
$pkginfo_seek = 0;
$pkgmap_start = 0;
foreach $p_head (@p_headers) {
if ( $output_dir eq 1 && $pkginfo_seek == 0 ) {
$output_dir = $p_head;
$output_dir =~ s/^(\w+)\W*.*$/$1/;
chomp($output_dir);
$pkginfo_seek = 1;
} elsif ( $output_dir eq 0 && $p_head =~ /datastream/i ) {
$output_dir = 1;
} elsif ( $output_dir eq 0 && $pkginfo_start == 0 ) {
next;
} elsif ( $output_dir ne 0 && $p_head =~ /pkgmap/ ) {
$pkgmap_start = 1;
$pkginfo_start = 0;
} elsif ( $pkgmap_start == 1 && $p_head =~ /pkginfo/ ) {
chomp($p_head);
push(@pkgmap, $p_head);
last;
} elsif ( $output_dir ne 0 && $p_head =~ /pkginfo.*PKG=/ ) {
$pkginfo_start = 1;
} elsif ( $output_dir ne 0 && $pkgmap_start == 1 ) {
chomp($p_head);
push(@pkgmap, $p_head);
} elsif ( $output_dir ne 0 && $pkginfo_start == 1 ) {
chomp($p_head);
push(@pkginfo, $p_head);
}
}

mkdir("$output_dir");
chdir("$output_dir");
open(PKGINFO_OUT, ">>pkginfo");
foreach $info (@pkginfo) {
print PKGINFO_OUT "$info\n";
}
close(PKGINFO_OUT);
open(PKGMAP_OUT, ">>pkgmap");
foreach $map (@pkgmap) {
print PKGMAP_OUT "$map\n";
}
close(PKGMAP_OUT);
open(RPM_SPEC_FILES, ">>${pkg_name}.specfiles");
foreach $specfile (@pkgmap) {
@specfile = split(" ", $specfile);
if ( $specfile[1] !~ /^d$/ && $specfile[2] =~ /^none$/ ) {
print RPM_SPEC_FILES "$specfile[3]\n";
}
}
close(RPM_SPEC_FILES);
system("cpio -iv <../$pkg_name.cpio >/dev/null 2>&1");
chdir("reloc");
system("tar cpf - *|(cd ../;tar xpf -)");
chdir("../");

$rpm_name=$pkg_name;
chomp($starting_point=`pwd`);
$temp_var=$$;

system("mkdir ${starting_point}/BUILD");
system("mkdir ${starting_point}/SOURCES");
system("mkdir ${starting_point}/SPECS");
system("mkdir ${starting_point}/SRPMS");
system("mkdir ${starting_point}/RPMS");
system("mkdir ${starting_point}/RPMS/noarch");
system("mkdir ${starting_point}/RPMS/`uname -i`");
system("mkdir $temp_var");
system("cd $temp_var");
open(PKGINFO_RPM, "<${starting_point}/pkginfo");
@pkginfo_rpm = <PKGINFO_RPM>;
close(PKGINFO_RPM);
($pkgrpm_name,$pkgrpm_arch,$pkgrpm_version,$pkgrpm_category,$pkgrpm_vendor,$pkgrpm_email,$pkgrpm_pstamp,$pkgrpm_basedir,$pkgrpm_classes) = @pkginfo_rpm;
$pkgrpm_name =~ s/.*=(.*)\n$/$1/;
$pkgrpm_arch =~ s/.*=(.*)\n$/$1/;
$pkgrpm_version =~ s/.*=(.*)\n$/$1/;
$pkgrpm_category =~ s/.*=(.*)\n$/$1/;
$pkgrpm_vendor =~ s/.*=(.*)\n$/$1/;
$pkgrpm_email =~ s/.*=(.*)\n$/$1/;
$pkgrpm_pstamp =~ s/.*=(.*)\n$/$1/;
$pkgrpm_basedir =~ s/.*=(.*)\n$/$1/;
$pkgrpm_classes =~ s/.*=(.*)\n$/$1/;
open(RPM_SPECIFICS, ">>$rpm_name.spec");
print RPM_SPECIFICS "%define _topdir $starting_point\n";
print RPM_SPECIFICS "Summary: $pkgrpm_name $pkgrpm_version\n";
print RPM_SPECIFICS "Name: $pkgrpm_name\n";
print RPM_SPECIFICS "Version: $pkgrpm_version\n";
print RPM_SPECIFICS "Release: 1\n";
print RPM_SPECIFICS "Copyright: $pkgrpm_pstamp\n";
print RPM_SPECIFICS "Group: $pkgrpm_category\n";
print RPM_SPECIFICS "Prefix: $pkgrpm_basedir\n";
print RPM_SPECIFICS "%description\n";
print RPM_SPECIFICS "Vendor = $pkgrpm_vendor - Email = $pkgrpm_email - Arch = $pkgrpm_arch - Classes = $pkgrpm_classes\n";
print RPM_SPECIFICS "%files\n";
open(RPM_SPEC_FILES, "<${starting_point}/$pkg_name.specfiles");
@specks = <RPM_SPEC_FILES>;
close(SPECKS);
foreach $speck (@specks) {
print RPM_SPECIFICS "${starting_point}/$speck\n";
}
close(RPM_SPECIFICS);

system("rpmbuild -bb $rpm_name.spec 2>&1|grep -v twice");
chdir("../");
system("mv -f ${starting_point}/RPMS/*/* .");
system("rm -rf $output_dir");
unlink "$pkg_name.headers";
unlink "$pkg_name.cpio";


, Mike




Tuesday, March 25, 2008

Creating Linux RPM's From Already Installed Packages

rpm_remk creating a new Mutt RPM


Click on the image for a higher resolution version of the output shown above!

Hey there,

Today's post is a follow up to, or the complement of, a post we did a little while ago on creating Solaris pkg files from already installed packages. Yes, there was a reason today's title sounded familiar ;)

Actually, I've been meaning to follow up on the Linux counterpart of this issue for a week or so now, but got caught up trying out various things. For instance, one of the more unusual (and interesting things) I ran across was a Perl project called alien that endeavours to pretty much translate between almost all package formats (dpkg, rpm, pkg, etc), but it didn't really address this specific issue. Still, pretty neat and in the experimental stage.

I also followed a lot of trial and error using rpmrebuild and standard rpm with the --repackage option, but found that both of these methods required the additional execution of at least one thing I didn't need to do to achieve my goal. For instance, using rpm with the --repackage option requires that you be upgrading, re-installing, deleting, etc, the RPM in question. All I want to do is create a package from existing source, and I'd rather not have to upgrade, re-install or delete the software on a live system to do it :)

Luckily, in the end, it boiled down to a fairly simple process. A lot of confusion came from various interpretations of the rpmbuild "spec file" and how, and why, it should be used. Many of the ideas I got that led me to an eventual solution came off of message boards rather than official sources. To put it somewhat humorously, a lot of those guys may not know what they're talking about, but they sure do know what they're doing ;) Seriously, if it weren't for the folks who strayed from the info-docs, this solution might have taken even longer to come around to.

You can call today's command (which I've name "rpm_remk" to remind me of my similar Solaris pkg project), very simply from the command line, like so:

host # ./rpm_remk mutt <--- If, for example, you wanted to create an RPM of the installed version of "mutt" on your system.

You can be as specific or general as RPM will let you when you use this command. For instance, on my box, I only have one instance of mutt:

host # rpm -qa|grep mutt
mutt-1.5.6i-64.9


So that simple command line suffices. For another program like, say, xaw3d, I would have to be more specific, because the underlying RPM system wouldn't know which package I was referring to. For example:

host # rpm -qa|grep xaw3d
xaw3d-1.5E-216.3
xaw3d-32bit-9-200407011229


Shows two different selections. RPM generally only picks the first one, like this:

host # rpm -q xaw3d
xaw3d-1.5E-216.3


So, if we ran the command with only "xaw3d" as the argument, we'd create that 1.5E RPM, which would be great unless we wanted the 32bit version ;) Specifying "xaw3d-32bit-9-200407011229" as the argument would guarantee that the intended RPM got built!

Here's hoping this script helps you out and makes it a little easier for you to retrieve some of those old installed software packages for which the original RPM's have long since disappeared :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/bash

# rpm_remk - Create new RPM's from installed RPM's
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

trap 'rm -rf $temp_var;exit 1' 1 2 3 9 15
if [ $# -ne 1 ]
then
echo "Usage: $0 PackageName"
exit 1
fi

existing_rpm=$1
starting_point=`pwd`
temp_var=$$

mkdir ${starting_point}/RPMS
mkdir ${starting_point}/RPMS/noarch
mkdir ${starting_point}/RPMS/`uname -i`
mkdir $temp_var
cd $temp_var

if [ `expr match \`rpm -q --queryformat "%{INSTALLPREFIX}\n" $existing_rpm\` '(none)'` -ne 0 ]
then
Prefix="/"
else
Prefix=`rpm -q --queryformat "Prefix: %{INSTALLPREFIX}\n" $existing_rpm`
fi

echo "%define _topdir $starting_point" >>$existing_rpm.spec
rpm -q --queryformat "Summary: %{SUMMARY}\n" $existing_rpm >>$existing_rpm.spec
rpm -q --queryformat "Name: %{NAME}\n" $existing_rpm >>$existing_rpm.spec
rpm -q --queryformat "Version: %{VERSION}\n" $existing_rpm >>$existing_rpm.spec
rpm -q --queryformat "Release: %{RELEASE}\n" $existing_rpm >>$existing_rpm.spec
rpm -q --queryformat "Copyright: %{COPYRIGHT}\n" $existing_rpm >>$existing_rpm.spec
rpm -q --queryformat "Group: %{GROUP}\n" $existing_rpm >>$existing_rpm.spec
echo "Prefix: $Prefix" >>$existing_rpm.spec
description=`rpm -q --queryformat "%{DESCRIPTION}\n" $existing_rpm`
echo "%description" >>$existing_rpm.spec
echo "$description" >>$existing_rpm.spec
echo "%files" >>$existing_rpm.spec
rpm -ql $existing_rpm|while read x
do
echo "%{prefix}$x" >>$existing_rpm.spec
done

rpmbuild -bb $existing_rpm.spec 2>&1|grep -v twice
cd $starting_point
mv -f ${starting_point}/RPMS/*/* .
rm -rf $temp_var ${starting_point}/RPMS


, Mike




Friday, March 14, 2008

Using Pkgbuild To Build Solaris Pkg Files Just Like Linux RPM's

Hello again,

If you're a regular reader, you've probably noticed that I've been spending a whole lot of time looking at ways to build packages, automate installations, etc, on both Linux and Unix ;) One interesting thing I found in my downloading, testing and trial is an ambitious project called pkgbuild, which is a good attempt (ongoing, and getting better) at addressing Solaris' pkg creation system and making it as versatile and security-conscious as RedHat's "rpmbuild" (That we took a look at a lot more than a few times in our series on creating your own RPM's.

The software's two main attractions are that it:

1. Addresses the "spec file" format for configuring software builds, just like rpmbuild

and

2. It works just about the same way. For instance, if you had your "spec file" written up and were ready to compile the source and binary pkg's for your build, you could do it almost exactly the same way we built our RPMS. The only difference on the command line, in fact, is the name of the command:

host # pkgbuild -ba PROGRAM.spec <--- eerily familiar ;)

The "spec file" format is almost identical to rpmbuild, except that there are some specific Solaris pkg tags that need to be used within the "header section" (Since, technically, you're still building a package and we know what Sun expects from Solaris pkg's "pkginfo" file. The following extra defines are specific to the pkgbuild software's "spec file":

SUNW_BaseDir "DIR" <--- Same as BASEDIR in the pkginfo file. Defaults to /, just like on Solaris.

SUNW_Pkg "PKG_NAME" <--- Same as NAME. Like SUNWblah

SUNW_ProdName "PRODNAME" <--- Same as SUNW_PRODNAME. Usually "SunOS"

SUNW_ProdVers "VERSION" <--- Same as SUNW_PRODVERS. For instance "5.9" for Solaris 9.

SUNW_Category "CATEGORY" <--- Same as CATEGORY. Generally "application"

SUNW_HotLine "WHO TO CALL" <--- Same as HOTLINE. Can include an email or who to contact about the pkg. Not necessary, but available :)

The list is actually fairly extensive and still growing. You can check it out here in the pkgbuild online manual

They also include support for %include directives, as well as all the stuff you'd expect, like inline macros for doing the "configure," "build," and "install" portions of your pkg creation.

The only downside (and it's pretty big) that I see so far is that the pkgbuild format and build process doesn't meld seamlessly enough to make it what I think it's trying to be (a way to provide admins with one simple way to create both Linux RPM's and Solaris pkg's). At this point, in the end, it's basically making you jump through a lot of hoops to get it to do what you would normally do if you were making the pkg file yourself. Still, it's early and I haven't counted it out yet.

I'll be writing more about this as I get into it and work it into our business practices. Until then, it might be worth checking out. If your business involves creating and/or packaging software installations for Solaris, this will, at the very least, be highly interesting :)

Best wishes,

, Mike




Thursday, March 6, 2008

Finalizing The Spec File And Building Your Own Linux RPM

Hey There,

We're finally ready to create our very own Linux RPM package! Following up on yesterday's post regarding beginning to write your spec file and the preceding initial software build, we're now going to look at the "build" section of the RPM spec file and compile our new RPM.

The "build" section of the spec file follows the "header section" we went over previously, and contains all that the "rpmbuild" command needs to know in order to create your RPM for you. I should note here that, on some systems, this command may be called "rpm-build" and, on yet others, the rpmbuild flags may simply be options to the rpm command itself (as with SUSE 8.x)

The declarations required in this section are:

%clean <--- Well, not really required, but keeps things nice and tidy ;)
%prep
%setup
%files
%build
%install


These sections are defined as follows (Note that for these declarations, the values are listed beginning on the line below, rather than on the same line, as we did in the "header section":

%clean - this deletes everything in the RPM_BUILD_ROOT, as defined by either the BuildRoot declaration in the "header section" (Which we didn't use for this build) or by the system default. In our case, this should be /usr/src/packages/BUILD. Cautious users may want to add a line of code in front of this, assuring that the RPM_BUILD_ROOT variable isn't set to /. This method is not absolutely necessary, either, so the incredibly cautious can just not call it and remove old garbage files, whenever they want to, manually. It can also cause issues when running concurrent builds if using the same RPM_BUILD_ROOT! Some folks prefer to run this method at the end of the spec file, or script out what it does automatically. It's a matter of preference :)

%prep - This simply indicates that we're moving on to the next section of our spec file. It is necessary, as everything beyond it will be considered part of the build process, rather than part of the RPM definition process, listed above it.

%setup - This part of the spec file indicates that "rpmbuild" should do whatever is necessary to prepare the source for building/compilation. Of course, we've done this already (to make sure we could build from source properly), but this declaration is necessary so that rpmbuild sets everything up for the following sections. Note that without any arguments, in our setup, it's just going to unzip and untar our source package in /usr/src/packages/SOURCES to the /usr/src/packages/BUILD directory.

%files - This is where we have to list all of the files that are going to be in our RPM, for reference when its installed and/or removed using the "rpm" command. In our previous post on building the software from source, we created a file called FILELIST (from the output of the find command). On the line following the %files declaritive, you can just read that file list into your spec file. If you elect to type each file name in, that's your decision, but you should include only one file per line (which can make your spec file pretty long depending on what you're installing. Given how many files most software packages contain, you'll grow sick and tired of this method soon enough ;)

%build - Here you'll provide all the information required to build the software. This can be culled from the notes you took while compiling the program initially.

%install - And finally, here you'll provide all the information required to install the program (Basically, the "make install" command and all arguments from the original compile of the software that you did earlier.

Our spec file will look something like this:

%clean
%prep
%setup
%files
/usr/local/PACKAGE-3.2-1/bin/list
/usr/local/PACKAGE-3.2.1/lib/liblist.so
...
%build
./configure --prefix=%{prefix}
make
make check
%install
make install
/bin/chown -Rv root:root %{prefix}


Before we actually build our RPM, we'll want to change the names of all the files listed in the %files section, that we got from our initial build. Assuming you wanted the RPM to install in /usr/local, you would want to use your favorite editor to replace all instances of "/usr/local/PACKAGE-3.2-1" in this section with "/usr/local" - this would change our %files section from:

%files
/usr/local/PACKAGE-3.2-1/bin/list
/usr/local/PACKAGE-3.2.1/lib/liblist.so
...


to

%files
/usr/local/bin/list
/usr/local/lib/liblist.so
...


Now our spec file is complete and we can create our RPM using this one simple command: rpmbuild. For our purposes, we'll run:

host # rpmbuild -ba PACKAGE.spec

then we'll kick back and watch the magic happen :) Note that I used the "-ba" option to build both source and binary RPM packages. This created the files /usr/src/packages/SRPMS/PACKAGE-3.2-1.src.rpm and /usr/src/packages/RPMS/x86_64/PACKAGE-3.2-1.x86_64.rpm <--- Note that this directory may be slightly different depending on what OS version of Linux you're running.

Now, you're all set to run "rpm -ivh PACKAGE-3.2-1.x86_64.rpm" and your software package will be installed, and can be manipulated by all the standard "rpm" facilities.

Of course there are tons of other options and additions to the spec file (%post, etc) and rpmbuild command, but this should be enough to get you started. For more specific information, check out the online man pages and chat boards - You'd be surprised at what you can do with this software if you use your imagination :)

Best wishes,

, Mike




Wednesday, March 5, 2008

Beginning Your Spec File For Building Linux RPM's.

Hello Again,

This is a continuation of yesterdays post on doing the initial build of your software as the first step toward creating your own Linux RPM. Today we're going to continue on that path with our software package (cleverly named PACKAGE-3.2-1 ;) and move on to the next step in the RPM creation process; the creation of the specification file (which I'll refer to as the "spec file" from here on out) and its basic structure.

For the purposes of our example, we won't be including every single option you can include in a spec file, but we'll touch on all the required ones, and a few that might make your life a bit easier :)

We'll create our spec file by simply opening it up as a new file in our favorite editor. The spec file is simply a plain text file, describing our RPM's attributes, that we'll be supplying to the "rpmbuild" command later on. We'll look at the spec file, line by line, for our soon-to-be-completed package. We'll call it PACKAGE.spec

The first section is what I like to call the "header section," although I don't know that it's ever actually referred to as that. It looks like the following

Summary: The World Famous PACKAGE software
Name: PACKAGE
Version: 3.2
Release: 1
Copyright: Gnu Public License
Group: Applications
Source0: PACKAGE-3.2-1.tar.gz
Prefix: /usr/local
Provides: PACKAGE3, PACKAGE-devel, bunk
Requires: PACKAGE1, db
URL: http://xyz.com
Packager: Mike Tremell
# %define _topdir /users/me/softbuilds/rpm
%description
PACKAGE 3.2-1 Standard Build
%define PACKAGEDIR %{prefix}


The lines in this section are defined as follows:

Summary - This line should be a descriptive summary of your RPM package, in short form. It shouldn't be too wordy, but you can make it as long as you want.

Name - This is simply the name of your package. It must match the source package's name (which we created in /usr/src/packages/SOURCES/ in yesterday's post on setting up the initial build for your RPM. It will later be used (with the Version and Release keyword values appended) by rpmbuild to determine what source file it should look for in /usr/src/packages/SOURCES

Version - The version of your software. Again this must be exactly the same version of the source package you're building from.

Release - The release of the software. This, again, must be exactly the same as the release you're building from. Using the "Name," "Version," and "Release" variables, rpmbuild will surmise that we want to build our RPM from PACKAGE-3.2-1.tar.gz in /usr/src/packages/SOURCES. Note: The Release variable is required and (for whatever reason) cannot be an empty value. Thus we put in the obligatory 1 for our new build of the generic PACKAGE software. Whatever you're building will probably have a release number.

Copyright - Just attribution for the package and/or package source's author(s)

Group - This identifies our package as belonging to the "Applications" package group in Linux.

Source0 - The name (Yes, this is redundant ;) of the source package in /usr/src/packages/SOURCES. As the name implies, you can have more than one source in certain circumstances. Note that there is also a "Patch0," etc, declaration that you can use to specify diff files you may need to include, but that's beyond the scope of our exercise.

Prefix - The root under which the RPM will install itself. Note: You need to include the Prefix declaration if you want your RPM package to be "relocatable." If your package is not relocatable, all installs will always install to the same place. If your package is relocatable, it allows the user or administrator to change the prefix, or root install directory, of the RPM when they run the "rpm" command to install it!

Provides - What your RPM will "provide" once it is installed. This is mainly for rpm's dependency checking. You can have your package provide anything, but it's best to have it provide only useful values. This variable isn't necessary if your software package isn't providing anything significant and/or doesn't have another package that's dependant on it.

Requires - The RPM packages your RPM package needs to have installed on your system before it will install correctly. In our example, PACKAGE will not install correctly (it will fail the dependency check) if some version of the "db" (Berkeley Database) RPM isn't already installed on our system.

URL - The location where a user can download the latest version of the RPM source. Not necessary, but can be helpful.

Packager - The name of the guy (or gal) who put together the RPM. Again, not necessary unless you're seeking notoriety ;)

# %define _topdir /users/me/softbuilds/rpm - Note that this line is commented out for our build, since we're going with the system defaults. However, comments in spec files work just like comments in shell scripts, so if you wanted to change the top level directory for your RPM structure, you could do it by redefining the _topdir variable (In this case, simply by removing the comment). You may need to create its required BUILD, BUILDROOT, RPMS, SOURCES, SPECS and SRPMS subdirectories manually. This option is useful if you're trying to do a build as a regular user and don't have the system privilege that will allow you to manipulate your server's main RPM package working directories :)

%description - Just like the summary above, but should be more descriptive. Also, you should add your description on a new line following the %description declaration (unlike all the others). "rpmbuild" will spew error messages if you put your description's value on the same line as the variable. You can actually include "one" word on the same line as the %description variable, but the rest of your description must be below that line. It should also be noted that you can have multiple %description declarations, which is useful if you're building multiple RPM's from one spec file (although that's deeper than we want to go for now).

%define - This directive can be used over and over again. It's simple format is: %define variable_name value. You can call the variable name you define here using the %{} notation. For instance:

%define mydir /usr/local/bin

Would allow you to reference /usr/local/bin, at any point (from the point of definition on) in your spec file as %{mydir}

Tomorrow, we'll check out the next, and final section of the RPM spec file and use "rpmbuild" to create our RPM package!

Cheers,

, Mike