|
|
  Building from source is fun, but it's easier to distribute RPMs to a
bunch of machines. You may recall that we recently built and installed
the OpenTDS libraries and SQSH, a dandy little command line tool for
use with MS SQLServer. These built nicely on my RedHat 7.3 system, and
I have a bunch of other developer workstations running the same OS.
So let's roll these tools into a couple of RPMS for easy distribution.
First, I must refer you to the excellent RPM HOWTO and its section on building RPMS. You really don't
need me to tell you how to build RPMs, because this HOWTO is great. But sometimes it's nice
to walk through a couple of examples together. We are building these RPMS
on a Red Hat 7.3 workstation, using the default build directories provided
by Red Hat under /usr/src/redhat.
[usr-3@srv-3 redhat]$ ls -l
total 20
drwxrwxr-x 3 root wheel 4096 Apr 17 11:37 BUILD
drwxrwxr-x 8 root wheel 4096 Dec 31 2001 RPMS
drwxrwxr-x 2 root wheel 4096 Apr 17 12:16 SOURCES
drwxrwxr-x 2 root wheel 4096 Apr 17 13:36 SPECS
drwxrwxr-x 2 root wheel 4096 Apr 18 2002 SRPMS
|
Basically, when we build an RPM, we're scripting a source build and install. We
resolve dependencies (or at least build an awareness of them into
our package), we define build-time configuration options, and are
able to add any additional tasks we desire, such as creating
users, setting up rc scripts, adding cron jobs. This allows us to easily
deploy a highly customized build/installation of a package.
The Spec File
All of the customizations mentioned above are defined in the spec file, which
we will put in /usr/src/redhat/SPECS. The spec file should be named according
to the following convention: package name-version number-release number.spec
For our freetds RPM, we're going to create freetds-0.61-1.spec. Our file is
going to be very simple, a bare bones build and install. We've already tested the build in our article
about SQSH, so we can skip that step. Let's set up our spec file:
The header section:
Summary: FreeTDS libraries for Sybase/MSSQLSVR
Name: freetds
Version: 0.61
Release: 1 the version of the RPM
Copyright: GPL
Group: Development/Tools the group the package belongs to in Red Hat installer
Source: http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-0.61.tgz
note: this file name must be the same as you're using to build
|
The description is self-explanatory:
%description
Libraries for connecting to Sysbase/MSSQSVR DBs. Used by Perl DBD:Sybase
and sqsh.
|
The following sections define how the package is to be built and installed:
%prep shell commands to be executed before build. also macros
are available for this section, see the HOWTO. This would be
the place for adding special users, patching the sources, etc.
%setup
./configure --prefix=/usr/local/freetds --enable-msdblib --with-tdsvr=7
%build
make
%install
make install
%clean
|
In the files section, you must list all of the files to be included in
the package. There is really no way to come up with this list until you
have built the package. There is also no easy way to generate the list. Luckily, in the case of freetds, every file is installed
under the /usr/local/freetds directory.
%files
/usr/local/freetds
|
Changelog: list changes made with each modification of the RPM.
Here's a link to the spec file in all its glory.
Building the RPM
Before we can build it, we need to put the tarball in /usr/src/redhat/SOURCES.
OK, let's give it a whirl. We will use -b (build) a(both source RPM and binary RPM)
[root@srv-3 SPECS]# rpm -ba freetds-0.61-1.spec
--snipping profuse output from configure and make--
Processing files: freetds-0.61-1
Finding Provides: (using /usr/lib/rpm/find-provides)...
Finding Requires: (using /usr/lib/rpm/find-requires)...
Provides: libct.so.1 libsybdb.so.3 libtds.so.2 libtdssrv.so.1
PreReq: rpmlib(PayloadFilesHavePrefix) <= 4.0-1 rpmlib(CompressedFileNames) <=
3.0.4-1
Requires(rpmlib): rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(CompressedFileNames) <= 3.0.4-1
Requires: ld-linux.so.2 libc.so.6 libncurses.so.5 libnsl.so.1 libreadline.so.4
libsybdb.so.3 libtds.so.2 libtdssrv.so.1 libc.so.6(GLIBC_2.0)
libc.so.6(GLIBC_2.1) libc.so.6(GLIBC_2.1.2) libc.so.6(GLIBC_2.1.3)
Wrote: /usr/src/redhat/SRPMS/freetds-0.61-1.src.rpm
Wrote: /usr/src/redhat/RPMS/i386/freetds-0.61-1.i386.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.84503
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd freetds-0.61
+ exit 0
|
And we're cool. The binary RPM will be written in RPMS under the directory
corresponding to the build system's architecture. Check it out:
[root@srv-3 SPECS]# ls -l ../RPMS/i386/
total 2408
-rw-r--r-- 1 root root 2129073 May 22 15:31 freetds-0.61-1.i386.rpm
|
The source RPM will be located under SRPMS. No architecture specific directories
there. Let's build an RPM for sqsh, then we'll install them both on
another system to make sure they work.
Building Another RPM
Step 1. The spec file.
This one has a slightly more complicated %prep section:
%prep
%setup -n sqsh-2.1
export SYBASE=/usr/local/freetds
./configure
|
We have to use a setup macro because of the way the tarball is named.
In our SOURCES dir, we have a tarball called sqsh-2.1-src.tar.gz. But
when this is expanded, the resulting directory is called sqsh-2.1,
*not* sqsh-2.1-src as rpm would guess. So we use the "-n" setup
macro to tell rpm that the build directory will be called sqsh-2.1.
Also in this section, we must export the SYBASE environmental variable
to get a good build.
Step 2. Build it:
Note: this time we're just going to build the binary RPM.
[root@srv-3 SPECS]# rpm -bb sqsh-2.1.spec
--profuse output from configure and make--
Processing files: sqsh-2.1-1
Finding Provides: (using /usr/lib/rpm/find-provides)...
Finding Requires: (using /usr/lib/rpm/find-requires)...
PreReq: rpmlib(PayloadFilesHavePrefix) <= 4.0-1 rpmlib(CompressedFileNames)
<= 3.0.4-1
Requires(rpmlib): rpmlib(PayloadFilesHavePrefix) <= 4.0-1
rpmlib(CompressedFileNames) <= 3.0.4-1
Requires: ld-linux.so.2 libc.so.6 libct.so.1 libdl.so.2 libm.so.6
libtds.so.2 /bin/sh libc.so.6(GLIBC_2.0) libc.so.6(GLIBC_2.1)
Wrote: /usr/src/redhat/RPMS/i386/sqsh-2.1-1.i386.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.91986
+ umask 022
+ cd /usr/src/redhat/BUILD
+ cd sqsh-2.1
+ exit 0
|
Looks good. Now let's install them on some innocent, untouched system.
Testing
[root@victim1 src]# rpm -i freetds-0.61-1.i386.rpm
[root@victim1 src]# rpm -i sqsh-2.1-1.i386.rpm
[root@victim1 src]# sqsh -S mickey -U bb
sqsh-2.1 Copyright (C) 1995-2001 Scott C. Gray
This is free software with ABSOLUTELY NO WARRANTY
For more information type '\warranty'
Password:
src/tds/login.c: tds_connect: 10.50.90.1:4000: Connection refused
Open Client Message
Layer 0, Origin 0, Severity 78, Number 41
Server is unavailable or does not exist.
|
Oops!! How did this happen? I did not take advantage of the power of RPM
to tweak my automated install of the freetds package, which requires a
configuration similiar to oracle's tnsnames for every SQLServer you
connect to.
Building a Better RPM
Maybe we can rebuild the RPM, this time inserting a
default server configuration into the freetds.conf file. I'm going to
uninstall the RPMs from our victim system, clean up the build system,
and try again. In cleaning up the build system, I will remove the
already-existent /usr/local/freetds directory, to make sure that
rpm doesn't use the files from the old install in making the new rpm.
I am making a new spec file, freetds-0.61-2.spec, for the new version of the RPM. Here's what I'll include in the install section:
%install
make install
cat >> /usr/local/freetds/etc/freetds.conf << EOF
[MICKEY]
host = mickey.domain.com
port = 1433
tds version = 7.0
EOF
|
Now we'll try installing freetds and sqsh again on the victim.
Testing Again
[root@victim1 src]# rpm -i freetds-0.61-2.i386.rpm
[root@victim1 src]# rpm -i sqsh-2.1-1.i386.rpm
[root@victim1 src]# sqsh -S mickey -U usr-3
sqsh-2.1 Copyright (C) 1995-2001 Scott C. Gray
This is free software with ABSOLUTELY NO WARRANTY
For more information type '\warranty'
Password:
[2] mickey.tempdb.1> select count(*) from sysusers;
-----------
13
(1 row affected)
[3] mickey.tempdb.1>
|
There's the joy. I think you'll agree that rolling your own is a lot of fun when
you can put whatever you like inside.
|
|