On Wednesday 20 February 2002 07:28 pm, John F Davis wrote:

> I have to build some rpm's again at work.  I saw Rob had written a document
> on building RPM's.  Before I start another RPM building endeavor I would 
> like to read what he has written.  Anybody know where I can get a copy?

You should probably contact Rob directly for the final version.  I've 
attached a preliminary draft he sent me and some others for proofing.  I 
haven't heard from him since he left the trilug list, but I think that he 
intended to release it under an open license.

---Tom
* Overview -- building RPMs

  This document describes, using a concrete example, how to
build simple noarch, binary and source RPMs.

  A "binary" RPM will typically have a name like
"myprogs-3.4-5.i386.rpm," meaning it corresponds to the
"myprogs" package, version 3.4, build release 5, and
built for the i386 architecture.  Such an RPM would typically
contain one or more compiled (or binary) executables, and
would usually install those executables in a directory like
/bin, /usr/bin, /sbin or the like.  In addition, a binary
RPM would likely also contain supporting files such as 
configuration files, documentation files and so on.

  A non-architecture-dependent (or noarch) RPM, on the other
hand, is meant to contain architecture-independent files such
as text files, audio or video files, font files, perhaps even
script files such as shell or Perl programs, and is meant to 
be installed, as the name suggests, on any architecture.

  Finally, for either kind of RPM, you might want to create
the corresponding "source" RPM, which contains the original
source and build instructions and allows others to examine the
way you built your binary or noarch RPM and possibly rebuild
it themselves with other options.

  In order to keep things manageable, I'm not going to cover
every possible issue involved in creating RPMS, so this document
has been written in three parts.  The first part -- the majority
of this document -- describes what I consider essential information
that everyone needs to know to build basic RPMs.  The second
part is an entire section titled "Advanced issues," that you
might want to peruse once you have the basic stuff under 
control.  And there is a final section, "Stuff I didn't cover,"
which just lists topics that were waaaaay outside the scope
of a basic tutorial and that you can hunt down on your own time.

  For a complete coverage, see the book "Maximum RPM," available
online at www.rpm.org and on the Red Hat 7.2 Documentation CD.

  Finally, in terms of prerequisites, I'm going to assume that
you're already familiar with how to use the "rpm" command to 
do basic things like examine, install and remove RPMs.  In 
addition, if you haven't already, you should install the
"rpm-build" RPM, which is essential for rolling your own RPMs.
(For basic RPM management, you should use the "rpm" command
while, for building RPMs, you should use the newer "rpmbuild"
command.)

  And now, to work.

* The hypothetical scenario

  As a working example, I'm going to demonstrate first how to
build a noarch RPM, since that's slightly simpler than a
binary RPM.  I'll spend the next several sections discussing
the noarch RPM, then show how easy it is to extend that to
handle binary RPMs as well.  And now, the scenario.

  Imagine that, as employee Fred Berferd of Pics 'r' Us, Inc, 
you've been told to create a noarch RPM out of a collection of
images of various cats, along with the accompanying documentation
files README and ARTISTS that came with those images -- these
are the files that will be supplied to you by the artists or
photographers.

  In addition, just to make things a touch more interesting,
all RPMs built at this company must also contain the standard
corporate "LICENSE" file, as well as a corporate logo image file
"picsrus.jpg".  These two additional files won't come from the
artists -- as the RPM builder, it's your job to add those to
the eventual RPM.

  Since this will be the company's very first cat-pic-related RPM,
it will have the designations:

  package name: catpics
  version: 1.0
  release: 1

which suggests that the final RPM should have the name
catpics-1.0-1.noarch.rpm.  You've been told to build this RPM file 
so that, when the customer installs it on their system, it will
unload files and directories in the locations:

  /usr/local/catpics/<cat image files>  # including picsrus.jpg
  /usr/share/doc/catpics-1.0/{README, ARTISTS, LICENSE}

So, let's start building catpics-1.0-1.noarch.rpm.

* The RPM building directory structure

  While Red Hat Linux already provides a directory structure
under /usr/src/redhat for building new RPMs, these directories
are available only to root.  And since it's generally considered
a hanging offense to build new RPMs as root, you're typically
encouraged, as a non-root user, to duplicate that directory
structure under your home directory and build your RPMs there.

  So pick a reasonable top-level name (say "rpm"), and re-create
that directory structure:

  $ cd
  $ mkdir -p rpm/{SOURCES,SPECS,BUILD,RPMS,SRPMS}
  $ mkdir -p rpm/RPMS/{i386,i586,i686,noarch}
  $ mkdir rpm/tmp       # to be explained shortly
  
  In order of when you'll use these directories, here's what
they represent:

  SOURCES: Where you'll gather your initial collection of files,
           in some format, from which to build the eventual RPM.
           In our case, we'll start with all of the cat image
           files, plus the accompanying README and ARTISTS files.

  SPECS:   Where you'll create the "spec" file for the new RPM,
           which defines (among many other things) information about 
           the new RPM, how to build it, what files it should contain
           and where those files should be installed on the target
           host.

  BUILD:   This is the actual "build" directory, where the original
           sources may be processed to generate even more files to
           be added to the new RPM.  If you're building a noarch
           RPM, there may in fact be nothing to build, since you
           have all the files you need already.

           If, however, you're building a binary RPM from program
           sources, this is where you'd set up the source files and
           a Makefile, and create the object files and eventual
           executables.  Hence, the directory name "BUILD".

  tmp:     A temporary directory, under which you'll typically create
           the "build root" for the new RPM.  This is where you'll
           create a directory structure which contains all of the
           files and directories to be added to the new RPM, in
           exactly the directory structure they should be installed
           on the target host.

           In other words, once you finish the stage of "build"ing
           all of the files that should go in the new RPM, the
           build root will represent precisely their target directory
           structure.

  RPMS:    Where new RPMs will be placed for your inspection and
           approval.  New noarch RPMs will be placed in RPMS/noarch,
           new binary RPMs will go in RPMS/i386, and so on.

  SRPMS:   Where new source RPMs will go.

  Finally, you can force the "rpmbuild" command to use this directory 
structure by creating the configuration file ~/.rpmmacros, with the 
contents:

  %_topdir      /home/fred/rpm
  %_tmppath     /home/fred/rpm/tmp

  So let's start discussing each stage of the RPM build in detail.

* Building the tarball

  Your first job is to load, into the SOURCES directory, the
initial set of files delivered by the artists that will be
used to create the new RPM.  The most common format for the
source files is a "tarball" -- a gzipped tar archive.
Tarballs are standard since they are a convenient way to 
ship an entire collection of source files, plus the 
"rpmbuild" command has shortcuts for handling tarballs
automatically.

  If this is your first attempt at building a "catpics" RPM, 
tradition suggests that the tarball be named catpics-1.0.tar.gz,
or catpics-1.0.tgz for short.  If we assume a collection of
four cat pictures, the contents of the tarball might be:

  $ tar tvzf catpics-1.0.tgz
  catpics-1.0/
  catpics-1.0/pics/
  catpics-1.0/pics/jones.jpg
  catpics-1.0/pics/xena.jpg
  catpics-1.0/pics/clarence.jpg
  catpics-1.0/pics/elliott.jpg
  catpics-1.0/ARTISTS
  catpics-1.0/README

  Things to notice about the tarball:

  - It should have a top-level directory name that matches the RPM
    name and version that you plan to build.

  - It should contain everything that the artists or photographers
    were responsible for supplying.  Notice that they did *not*
    supply the corporate logo or LICENSE file -- that's your job.
    This is just demonstrating that you might need to get the
    contents for the proposed RPM from more than one source,
    not just a single tarball.

  - Most importantly, the location of the files in the tarball do
    *not* have to match their eventual location in the new RPM.
    Between extracting the files from the SOURCES directory and
    adding them to the build root, you have the freedom to change
    their locations to match the eventual directory structure.

    Specifically, the location of any documentation files like 
    README don't have to match their final location.  In fact,
    there is a tradition of putting doc files just under the 
    top-level directory in the tarball as the RPM-building
    process has a shortcut for dealing with doc files that are
    placed here.

  All right, now that you have your tarball, it's time to design
your spec file.

* The spec file -- "catpics.spec"
** What's a spec file?

  The "spec" file for a new RPM (whose name is typically
<package>.spec or, in our case, "catpics.spec") contains, 
among other things, the name and version of the RPM you're 
building, along with corporate information and detailed steps 
describing the sources, how to build those sources and how to 
package the resulting files to create the new RPM.
  
  More specifically, the spec file starts with a "preamble"
describing the properties of the new RPM, followed by the
instructions for the "%prep", "%build", "%install" and "%clean"
stages, as well as the "%files" section which lists precisely
which files you want to add to the RPM and where -- we'll
cover these stages one at a time.
  
  Technically, the spec file can be created anywhere, but it's
traditional to create it in your SPECS directory.  If, at any 
time, you want to see the spec file in its entirety, see 
the listing for "catpics.spec" in Appendix A.)

** The preamble

  Consider a possible preamble at the beginning of our
"catpics.spec" file:

----- begin preamble -----
  Summary: CatPics, a collection of feline images
  Name: catpics
  Version: 1.0
  Release: 1
  Copyright: GPL
  Group: Amusements/Graphics
  Source: ftp://ftp.picsrus.com/pub/%{name}-%{version}.tgz
  URL: http://www.picsrus.com/pub/pics/catpics.html
  BuildArch: noarch
  BuildRoot: %{_tmppath}/%{name}-root
  Vendor: Pics R Us, Inc.
  Packager: Fred Berferd <[EMAIL PROTECTED]>
  Requires: ee

  %description
  This package contains CatPics, just a collection of 
  feline images in various graphics formats, along with
  some documentation and corporate info files.
----- end preamble -----

  The preamble represents the information someone can see if
they query the eventual RPM with:

  $ rpm -qpi catpics-1.0-1.noarch.rpm

Some of these values should be obvious; some observations about
the rest:

  - The Group value should be one of the values from the file
    /usr/share/doc/rpm-4.0.3/GROUPS.  Strictly speaking, it 
    doesn't *have* to be, but you're strongly encouraged to use
    one of those combinations.

  - The Source value represents two things.  First, if the
    original tarball is available on the net somewhere, this
    value should refer to its location, typically in an FTP or
    HTTP archive.  More importantly, though, the last component
    of this value is used as a pointer to the tarball to be used
    from the SOURCES directory.  All this means is that it's only
    that last component that's really critical.  (You can also
    use the tag Source0 in place of Source -- the effect is the
    same.)

    Similarly, the URL value is not essential, and would just
    contain a pointer to information about that package that's
    available on the net.

  - BuildRoot represents the location where you plan on building
    the directory structure that will ultimately match the final
    structure in the RPM -- where things will go when the RPM is
    installed on the target host.

    As shown above, it's traditional to put all new build roots
    in the ~/rpm/tmp directory, in a subdirectory matching the name
    of the package.  In our case, this RPM's build root will be the
    directory ~/rpm/tmp/catpics-root, and it will be your job to
    copy under that directory what you want as the eventual file
    and directory layout of the final RPM.

  The rest of the preamble is fairly straightforward, and even 
demonstrates a simple package prerequisite -- you can require
that the "ee" package be installed on the target host before
this RPM can be installed.

  A final note:  you're allowed to have more than one Source
directive if you're collecting the source for this new RPM from
more than one location, but I'm not going to get into that
here.  As I said, I'd like to keep this simple.

  And now, on with the actual construction.

** The script variables (a huge footnote, really)

  Given that the rest of the spec file represents commands to be
run that will unload the tarball, process its contents and build 
a new RPM, it's worth pointing out that, at this point, the 
following variables are now available to use in any of these 
upcoming steps (shown with their values for our example):

  RPM_PACKAGE_NAME              catpics
  RPM_PACKAGE_VERSION           1.0
  RPM_PACKAGE_RELEASE           1
  RPM_ARCH                      i386
  RPM_OS                        linux
  RPM_SOURCE_DIR                /home/fred/rpm/SOURCES
  RPM_BUILD_DIR                 /home/fred/rpm/BUILD
  RPM_BUILD_ROOT                /home/fred/rpm/tmp/catpics-root

If you want to refer to any of them, you can use either, for
example, ${RPM_BUILD_ROOT} or just $RPM_BUILD_ROOT.

  One important note here: Don't confuse the "build directory" 
with the "build root" -- the build directory is where the tarball 
will be unloaded and processed, while the "build root" is where 
you will construct, piece by piece, an exact image of the files 
and directories to be contained in the RPM.  (It's unfortunate that 
this directory was called the "build root" -- calling it the
"install root" would have made much more sense.)

  Now, on to the first stage -- the "%prep" stage.

** The %prep stage

  The purpose of the %prep stage is simply to gather into the
appropriate "build" directory all of the sources you'll need
to build the new RPM.  Each new RPM should get its own build
subdirectory under the main build directory so this suggests
that, while the main build directory for all RPMs is 
~fred/rpm/BUILD (or ${RPM_BUILD_DIR} for short), the catpics-specific 
build directory will be ${RPM_BUILD_DIR}/catpics-1.0.

  Given that the purpose of the %prep stage is to unload the
catpics source into the corresponding build directory, we
could, if we wanted, do this manually with something like:

  %prep
  cd ${RPM_BUILD_DIR}
  rm -rf catpics-1.0                    # remove old version??
  gzip -dc ${RPM_SOURCE_DIR}/catpics-1.0.tgz | tar xvf -
  cd catpics-1.0                        # enter new dir

The end result of the above is that we end up at the top level
of a directory containing the contents of the catpics-1.0 tarball,
ready to start the build stage.

  However, unloading from a tarball is such a common procedure
that you can use the shortcut macro "%setup" in one of two ways
that does pretty much the same thing:

  %prep
  %setup                # regular setup or ...
  %setup -q             # ... quiet setup

In either case, the end result is the same, and you end up in
the catpics build directory, looking at the contents of the
catpics tarball:

  pics/jones.jpg
  pics/xena.jpg
  pics/clarence.jpg
  pics/elliott.jpg
  ARTISTS
  README

At this point, you've done the prep and can move on to the
"build" stage, except for one possible complication.

  Notice that we're still missing the corporate LICENSE file
and corporate graphics file from the catpics build directory.
If we really want *all* of the necessary source here in the
build directory before we go any further, we can just add
a couple of appropriate "cp" statements to the %prep stage,
as in:

  %prep
  %setup -q
  cp /etc/LICENSE .
  cp /etc/picsrus.jpg pics

(Before you start howling that this is *not* the recommended
way to do this, yes, I know.  What you would really do is
define multiple Source directives.  But I just wanted to
demonstrate how particular you can be in the %prep stage in 
terms of collecting other files to add to your RPM.)

  In any event, now that you've finished prepping, it's on to
the %build stage of the spec file.

** The %build stage

  Given that you're currently in the build directory for the
catpics RPM, this stage is where you'd do any "building" of
additional files that need to go in the new RPM.

  In the case of a binary RPM where you have to compile 
executables, this is where you would run things like "configure"
and "make" and "make install" to get the new executables --
hence the reason it's called a "build" directory.  In other
words, this is the stage where you have to somehow create
the contents of the new RPM that don't come directly from the
tarball.

  In our case, since we have all the contents we need and
have nothing to build, our entire build stage could be
nothing more than:

  %build
  exit 0

And since we didn't have to build anything, we can head right
into the "%install" stage.

  (Side note:  Even if we're building a noarch RPM, there are
always trivial things we might want to do in the build stage.
We might create a hidden timestamp file showing when this RPM 
was built by running something like:

  date > ./.TIMESTAMP

  It's also possible to copy the non-tarball LICENSE and
picsrus.jpg files in this stage rather than the %prep stage.
The end result is the same but, again, I'm just throwing this
in to demonstrate that you can customize this stage as well.

  Admittedly, these are pretty trivial examples, but they
demonstrate that, if there's anything you need to do to create
additional RPM contents that don't come directly from the tarball,
this is the place to do it.)

  Now, on to the %install stage.

** The %install stage

  Now that the %build stage has created (in the directory
${RPM_BUILD_DIR}/catpics-1.0) absolutely everything you need
to build the new RPM, the job of the %install stage is to
create, in yet *another* directory, an exact copy of the
files and directories, in their proper locations, of what
you want built into the new RPM.

  This new directory is called the "build root" of the new
RPM and is typically created under your RPM tmp directory.
In our case, the build root directory would be
~fred/rpm/tmp/catpics-1.0, whose value is, just in case you
need it, available in the variable ${RPM_BUILD_ROOT}.

  Your job, in the %install stage, is to copy step by step,
from the build directory, every file and directory you want
in the new RPM to the corresponding build root directory,
putting each of these in its target location relative to 
the root directory on down.

  Recall that we wanted the catpics RPM to install the 
following on the target host:

  /usr/local/catpics/<cat image files>  # including picsrus.jpg
  /usr/share/doc/catpics-1.0/{README,ARTISTS,LICENSE}

  Given the above, our entire %install section might be:
  
  %install
  rm -rf ${RPM_BUILD_ROOT}      # delete old build root
  mkdir -p ${RPM_BUILD_ROOT}/usr/local/catpics
  cp pics/* ${RPM_BUILD_ROOT}/usr/local/catpics

As you can see, the build root for this RPM should contain
everything you want in the new RPM, in its appropriate location
relative to the root directory.  Note that the eventual
directory structure does not have to match the way the files
and directories came out of the original tarball.  You clearly
have the flexibility to restructure the new RPM any way you
want.

  Note also that our %install stage didn't do anything with the
documentation files.  This is because doc files are considered
a special case, and can be treated separately in a later
section.  So, other than the missing doc files, we're pretty
much finished with the %install section.

  (Side note:  It's unfortunate that the directory we've been
populating is referred to officially as the "build root".
It would seem that the previous directory, whose name really
is "BUILD," would be better named the build root, while it
makes more sense to call this one the "install root".  But
it's too late now.)

  We're almost ready to build the new RPM -- only a couple
stages to go.

** The %clean stage

  When the RPM is eventually constructed, you have the
right to do some automatic cleanup by defining a %clean stage
here.  While you can clean as much as you want, the following
is a perfectly respectable example of cleaning:

  %clean
  rm -rf ${RPM_BUILD_ROOT}

Keep in mind that, while you define the %clean stage here, it's
not actually run until the end of a successful RPM construction.
So what's left?  Just the %files stage.

** The %files stage

  The final stage in our spec file, the %files stage, is used
to identify exactly which files and directories should be
copied from the build root into the new RPM.  Let me make
sure you understand this last statement.

  While the previous %install stage created a directory
structure for the new RPM under the build root, you have no
obligation to add *all* of these files and directories to
the RPM -- you can be selective about what gets added.
In other words, while it's a bad idea, you can be sloppy
and copy extraneous junk into the build root during the
%install stage -- you just don't need to select all of it 
for inclusion in the RPM.

  For our example, here's a respectable %files section:

  %files
  %defattr(-,root,root)
  /usr/local/catpics
  %doc README ARTISTS LICENSE

What does all this mean?

  First, you can, if you want, have a single %defattr directive,
which dictates the default permissions, owner and group you
want for the contents of the RPM.  A hyphen means that you'll
take the current value, whatever it is.

  Following the optional %defattr, you should list all of the
files and directories you want added to the RPM, using their
fully-qualified location as you want it on the target host.

  Finally, as you can see above, documentation files can be
treated specially.  Rather than having to explicitly copy
doc files into the build root, and select them here, you can
use the %doc directive, which will look for these files at 
the top of the build directory, and automatically install
these files in the appropriate documentation directory in 
the RPM (in your case, probably the default directory of
/usr/share/doc/catpics-1.0).  This is a convenient shortcut,
but remember that it means you have to have these files at
the top level of the build directory.

  This is clearly a simple example of a %files stage of a
spec file.  For more possibilities, see the section "Advanced
issues" for additional things you can do with the %files 
section and the documentation files.

  At this point, you might want to review the entire spec
file in Appendix A.

* Building a noarch RPM

  Using our original example, now that you have a 
"catpics.spec" file, you can create the corresponding
noarch RPM with:

  $ rpmbuild -bb catpics.spec     ("b"uild "b"inary)

This command will, in order and following the steps in the 
spec file:
  
  1) unload the SOURCES tarball into the BUILD/catpics-1.0
     directory,

  2) copy a couple of extra generic company files to go
     with those source files, 

  3) install these files under the corresponding build root, 

  4) select using the contents of the %files stage what
     should be added to the new RPM, 

  5) place this new RPM in the RPMS/noarch directory, and 

  6) run the %clean stage to get rid of the build root

  Once you run this command, you can examine the contents
of the new RPM with any of:

  $ rpm -qpi catpics-1.0-1.noarch.rpm           (preamble info)
  $ rpm -qpl catpics-1.0-1.noarch.rpm           (file list)
  $ rpm -qplv catpics-1.0-1.noarch.rpm          (long file list)

to make sure every file is there and seems to be in the right
location.  You now have a noarch RPM ready to ship to customers.

* Building a binary RPM

  Once you understand the details of building a noarch RPM, 
it's a small step to building a binary RPM like, say,
"myprogs-3.4-5.i386.rpm," which would typically contain one
or more compiled binary executables, along with possibly
some text files, documentation, configuration files and so on.

  Everything you've read so far would be pretty much the
same, except that the %build stage would be responsible for
taking the source files from the tarball and compiling them
to get the corresponding binary executables.

  Once you unload that tarball into the build directory,
you could compile the executables manually using, say,
the GCC compiler.  However, if you carefully design the 
contents of the tarball to include the sources, configure
scripts, Makefile and other files based on the GNU autoconf
utility, you might need to run little more than the commands:

  $ configure
  $ make
  $ make install

  In fact, this is such a common operation that rpm defines
some common macros so that your entire %build and %install stages
might look like:

  %build
  %configure
  %make

  %install
  %makeinstall

As an example, the "%makeinstall" macro is equivalent to running
a "make install", and using the appropriate build root as the
install destination, exactly what you would want.

  For those who want more detail, check the definition of 
these macros in the file /usr/lib/rpm/macros to see exactly
what they would do.

* Building a source RPM

  Assuming you understand the rationale behind building a
source RPM, you can build one in one of two ways:

  $ rpm -bs catpics.spec          (build just the source RPM)
  $ rpm -ba catpics.spec          (build both source and binary RPMs)

  In either case, what you should end up with is a source RPM
with the name catpics-1.0-1.src.rpm in your SRPMS directory.
If you query the file list from that source RPM, you should see
exactly two files -- the tarball and the spec file.

* Building from a tarball

  There is one more variation to building RPMs, and that is
from a completely self-contained tarball.  If you want, you
can embed the spec file somewhere in the tarball (it doesn't
have to be at the top), and run any of:

  $ rpmbuild -tb <tarball>
  $ rpmbuild -ts <tarball>
  $ rpmbuild -ta <tarball>

and so on -- you get the idea.

* Debugging using partial RPM builds

  There is one more feature involving building RPMs that's
useful for debugging your builds in case the end result
is not what you expected.
  
  With both noarch and binary RPMs, it's possible to do only a
partial build so that you can check the intermediate results
in, for instance, the build or build root directories.  So rather
than doing a complete catpics RPM build with "rpmbuild -bb", 
you can do any of the following:

  $ rpmbuild -bp catpics.spec           (%prep stage only)
  $ rpmbuild -bc catpics.spec           (%prep, %build)
  $ rpmbuild -bi catpics.spec           (%prep, %build, %install)

A common usage is to use "-bi", then check the contents of
the build root directory to see if it matches what you expect
to see in the eventual RPM.

  While all of the above start with the initial %prep stage, you
can also jump directly to a stage and execute that stage only
with the "--short-circuit" option:

  $ rpmbuild -bc --short-circuit catpics.spec   (%build ONLY)
  $ rpmbuild -bi --short-circuit catpics.spec   (%install ONLY)

The --short-circuit is available only for the -bc and -bi
options, and could be useful if you've alread done a partial
build up to that point, and now just want to do the next
stage.

  It is unfortunate that the name --short-circuit was chosen
for this option, since what it really refers to is jumping
directly to a stage and processing only that stage.  This 
option would have been more meaningfully called something like
"--single-stage" or "--this-stage-only".

* Ongoing RPM maintenance issues

  As you collect more nifty cat images, you may want to release
newer versions of the Pics 'r' Us catpics RPM file.  There are
two standard ways to build and release updated versions of an
RPM.

  First, if the change is simply a rebuild of the RPM, or perhaps
a change not in the contents but in, say, some permission or
owner/group attributes of files, it's reasonable to build the
new RPM and just increment the release/build number, as in 
catpics-1.0-2.noarch.rpm.

  If however, you've made major changes like replacing or adding
image files, it's more appropriate to increment the version 
number, to 1.1 or maybe even 2.0.

  In any case, you should log the history of changes in the
spec file's "changelog" section, which you can add at the
bottom of the spec file:

  %changelog
  * Mon Jan 1 2002 Fred Berferd <[EMAIL PROTECTED]> 2.0-1
  - threw out proprietary GIFs, replaced all images with PNGs

  * Tue Dec 25 2001 Fred Berferd <[EMAIL PROTECTED]> 1.2-1
  - removed images of Ethel's little hairball Snookums

  * Mon Dec 24 2001 Ethel Rosenkrantz <[EMAIL PROTECTED]> 1.1-1
  - added images of my little darling Snookums

  If you do this, anyone can see the contents of the RPM changelog
with one of:

  $ rpm -qp --changelog catpics-2.0-1.noarch.rpm
  $ rpm -q --changelog catpics

* Some rpmbuild options

  In addition to all of the rpmbuild options you've seen
so far, there are several others, including:

  --buildroot <directory>
  --rmsource            # remove sources after the build
  --rmspec              # remove spec file after the build
  --vv                  # be very verbose

  For more on these options, see "man rpmbuild".

* Advanced issues
** Defining multiple sources

  Recall that our catpics RPM depended on not only the images
provided by the artists, but also a couple corporate files that
you had to supply yourself.  While you can always copy these
files into the build directory manually (as we did), what you
really should do is define multiple source directives, making
it clear that your new RPM is getting its contents from a 
variety of locations:

  Source: catpics-1.0.tgz
  Source1: <additional source>
  Source2: <additional source>

and so on.  You can refer to the first source as either Source
or Source0, it doesn't matter.

  If you want to know more about multi-source spec files, you
should read the online documentation.

** The %files section

  Recall the fairly simple %files section we used to define the 
contents of our new RPM:

  %files
  %defattr(-,root,root)
  /usr/local/catpics
  %doc README ARTISTS LICENSE

So what does all this mean?  

  Ignoring the %doc line (which I'll explain in the next section), 
the purpose of the %files section is to list, with one entry per
line, every file and directory (with a fully-qualified name) to 
be copied from the build root directory into the new RPM.  By
default, a filename refers to only that file, while a directory
name refers to the entire recursive contents of that directory;
hence, our listing of "/usr/local/catpics".  So what else can
we do in this section?

  First, we can specify that we want to add only a directory
object, not its entire recursive contents, with the %dir directive:

  %dir /usr/local/catpics

This is useful if we're trying to add an empty directory, or we
want to be more selective about which of its contents we want to
add to the new RPM:

  %dir /usr/local/catpics               # add directory only ...
  /usr/local/catpics/xena.jpg           # ... and this file ...
  /usr/local/catpics/jones.jpg          # ... and this file

But there is another reason to treat directories separately.

  By default, files and directories added to the new RPM will
retain their original permissions, owner and group.  You can
override this by adding at most one %defattr directive in the
%files section, as in:

  %defattr(-,root,root)

This directive defines the new permissions, owner and group that
all objects will get; a hyphen in any field means to keep the
original attribute.

  In addition to this global attribute definition, you can 
add a per-line %attr directive, which takes precedence.  This leads
to combinations of global and local attribute settings such as
the following excerpt, extracted from a real spec file:

  %files
  %defattr(0755,root,root)
  /bin
  /boot
  /etc
  /initrd 
  /lib
  %dir /mnt
  %dir /opt
  %attr(555,root,root) /proc
  %attr(750,root,root) /root
  /usr/share/doc
  %attr(555,root,root) %dir /usr/share/empty   # two directives here

In short, you can combine the %defattr, %dir and %attr directives to
get precisely the file and directory attributes you want in the new
RPM.

  Finally, you can use the basic shell globbing feature in any
of the %files lines, as in:

  /usr/local/catpics/*.jpg

** Documentation files

  In addition to the other directives you can find in the 
%files section, you can also tag files or directories as
documentation files, which can be treated differently as
you'll see shortly.

  First, if you placed some doc files at the top of the
build directory, you can flag them as doc files with:

  %doc README ARTISTS

This not only marks them as documentation, but arranges
that they will automatically be copied into the RPM under
the default documentation directory; in your case, probably
/usr/share/doc/catpics-1.0.  If you use this method, there's
no need to copy these files to the build root yourself --
that will be done automatically.  As a variation of this,
you might have an entire directory of documentation at the
top of the build directory, say, under the name "docs", that
you can tag with:

  %doc docs

  If the doc files aren't at the top of the build directory,
you can always just refer to them explicitly and copy them
as you would normal files, as in:

  %doc /usr/local/catpics/docfile

  And, finally, if you have a non-standard directory that
will contain doc files, you can flag the entire directory as
a documentation directory, as in:

  %docdir /opt/catpics/doc

This means that all files in that RPM directory will also be
tagged as documentation files.  And just what is the value
of having something considered documentation?

  Once something has been tagged as a doc file, you can use
the "rpm" command to list strictly the documentation files in 
any RPM with:

  $ rpm -qpld catpics-1.0-1.noarch.rpm

  Additionally, if you're strapped for disk space, you 
(theoretically) have the right to install all *but* the
documentation files with the command:

  $ rpm -ivh --excludedocs catpics-1.0-1.noarch.rpm

(I say "theoretically" since, while this feature is officially
documented, I have yet to get it work that way.)

* Stuff we didn't talk about

  There's clearly a lot of topics I didn't cover here:

  - the details of using multiple sources
  - using patch files
  - install and uninstall scripts
  - spec file conditionals
  - building relocatable RPMs
  - signing packages with GPG
  - building subpackages

and a truckload more.  If you want to know more, I recommend
the online book "Maximum RPM," although that book is admittedly
getting a bit dated.

  Besides that, start at www.rpm.org and take it from there.

* In closing

  If you have any questions or comments, or suggestions on how
to improve this document, email me at [EMAIL PROTECTED]

  This document is copyright Robert P. J. Day, 2001.  All rights
reserved.  You're welcome to distribute this freely, but you're not
free to start making modifications to it until I release the
final version under the GNU FDL license.

* Appendix A: The spec file

  The contents of the spec file "catpics.spec":

Summary: CatPics, a collection of feline images
Name: catpics
Version: 1.0
Release: 1
Copyright: GPL
Group: Amusements/Graphics
Source: ftp://ftp.picsrus.com/pub/%{name}-%{version}.tgz
URL: http://www.picsrus.com/pub/pics/catpics.html
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-root
Vendor: Pics R Us, Inc.
Packager: Fred Berferd <[EMAIL PROTECTED]>
Requires: ee


%description
This package contains CatPics, just a collection of 
feline images in various graphics formats, along with a
couple of documentation files.

%prep
%setup -q
cp /etc/LICENSE .
cp /etc/picsrus.jpg pics

%build
exit 0

%install
rm -rf ${RPM_BUILD_ROOT}

mkdir -p ${RPM_BUILD_ROOT}/usr/local/catpics
cp pics/* ${RPM_BUILD_ROOT}/usr/local/catpics
touch ${RPM_BUILD_ROOT}/BOGUS

%clean
# rm -rf ${RPM_BUILD_ROOT}

%files
%defattr(-,root,root)
/usr/local/catpics
%doc README ARTISTS LICENSE

Reply via email to