rpm-guide rpm-guide-extra-packaging-tools-en.xml,NONE,1.1
Stuart Ellis (elliss)
fedora-docs-commits at redhat.com
Tue Oct 4 01:51:55 UTC 2005
Author: elliss
Update of /cvs/docs/rpm-guide
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv559
Added Files:
rpm-guide-extra-packaging-tools-en.xml
Log Message:
--- NEW FILE rpm-guide-extra-packaging-tools-en.xml ---
<!-- $Id: -->
<chapter id="ch-extra-packaging-tools">
<title>Supplemental Packaging Software</title>
<para>
Copyright (c) 2005 by Eric Foster-Johnson. This material may be
distributed only subject to the terms and conditions set forth in
the Open Publication License, v1.0 or later (the latest version is
presently available at http://www.opencontent.org/openpub/).
</para>
<para/>
<para>
In This Chapter
</para>
<para>
*Understanding packaging aids
</para>
<para>
*Manipulating packages
</para>
<para>
RPM is intended to make system management easier, both for system
administrators and other users who do all the day-to-day work of
installing and removing applications and for developers and other
users who do all the work of preparing applications for
installation. For RPM packagers, the work involved in preparing an
application for installation has two phases: first, the software
must be compiled (if it is not written in an interpreted language
such as Perl) and otherwise configured for the system on which it
will be installed; then the RPM package of the software must be
prepared by creating a spec file that properly packages it into an
RPM. In contrast, packagers who choose to package applications in a
simpler format, such as gzipped tarballs (compressed tar archives),
have less work ahead of them, since they need only concern
themselves with the first step.
</para>
<para>
After a packager has prepared an RPM package once, RPM makes the
first step (compilation and configuration) easier when the packager
has to package an updated version of the same software; RPM does a
lot of work to track compilation commands, any needed patches, and
any configuration modifications discovered to be necessary to
prepare the software. Similarly, once an RPM spec file has been
produced for an application, updating that spec file to support a
newer version of that application is usually trivial. For these
reasons, using RPM instead of a simpler, less end-user-friendly
package format (such as gzipped tarballs) is a bit of a tradeoff for
the packager; preparing an RPM of an application requires a little
more initial time and work than preparing a gzipped tarball of that
same application, but once created, the RPM package takes less time
and effort to keep current than the gzipped tarball requires.
</para>
<sect1>
<title>Packaging Aids</title>
<para>
However, several helper tools are also available for RPM
packagers. These tools can be used at various stages in the
process of producing a high-quality RPM package to simplify the
tasks that an RPM packager must perform. These tools include
syntax-highlighting modes for various text editors, making
production and maintenance of spec files easier; macro packages
for popular text editors, simplifying the generation and
maintenance of spec files; tools that generate spec files,
simplifying initial spec file creation; and debuggers that
validate produced binary RPMs, helping ensure that the spec file
used to create the packages is accurate and high quality.
</para>
<sect2>
<title>Using VIM spec plugins to improve spec file editing</title>
<para>
Unix systems have traditionally shipped the legendary (or
notorious, depending upon your point of view) vi editor
(pronounced vee eye) as their default text editor. Vi was
initially developed by Bill Joy in 1976 for BSD Unix. It
eventually was incorporated in AT& T System V Unix as well
and later was mandated by the POSIX 1003 standards (which define
what an OS must have to be Unix-compatible), thereby conquering
all facets of the Unix world.
</para>
<para>
The original vi source code is no longer freely available, but
several clones of the vi program have been created over the
years. The most popular of these vi clones is probably Vi
IMproved, or VIM (www.vim.org). VIM is the standard vi
implementation (meaning that when you type vi at the command
prompt, the program you really are running is vim) on many Linux
distributions, including Red Hat Linux. It is also freely
available for most other Unixes and even for non-Unix systems
such as Microsoft Windows.
</para>
<para>
VIM is a fully backwards-compatible implementation of the
original vi editor, although it also offers many additional
features that vi did not support. One VIM feature that can be
extremely useful when preparing spec files is colorized syntax
highlighting. VIM has an extensible interface through which it
can be told about the syntax used for files of various types.
Once it understands a filetype's syntax, it can color the
various syntactic structures of that file in different ways. For
example, when editing a Bourne shell script using VIM, comments
are typically blue, control statements (if, for, do, and so on)
are yellow, variables are purple, and so forth. Many people find
this feature very useful, since a single glance reveals the
entire logical structure of the file. Furthermore, errors in the
file (such as a missing done statement failing to close a do
loop in a Bourne shell script) are often immediately obvious
when using such a colorizing editor.
</para>
<para>
Usually, VIM does not understand the structure of RPM spec
files. When preparing a spec file, VIM displays all text in the
same color. A spec.vim syntax file is available for VIM that
makes VIM aware of the syntax used for RPM spec files. When this
file is used, the various structural components (%define,
preamble statements, %build, and so forth) are all colorized,
making the logic of the spec file readily apparent.
</para>
<para>
The spec.vim file that provides VIM with an understanding of
spec-file syntax is bundled with newer versions of VIM, or it
can be downloaded from the Internet. Most RPM-based Linux
distributions, including Red Hat Linux, ship this file with VIM
as part of their distribution and even automatically configure
VIM to load this syntax file any time an RPM spec file is being
edited. When using VIM on a system that does not automatically
load spec.vim whenever spec files are edited, you should
download the spec.vim file (I tend to save such personal
extensions in ~/etc/vim, but you can save it any place you
prefer).
</para>
<para>
Cross Reference
</para>
<para>
Download the spec.vim syntax file for VIM from
http://pegasus.rutgers.edu/~elflord/vim/syntax/spec.vim.
</para>
<para>
Once downloaded, configure VIM to load your new syntax file. You
can do this by putting the following in your ~/.vimrc file
(assuming you have saved the file as ~/etc/vim/spec.vim; adjust
the path as necessary if you saved it elsewhere):
</para>
<para>
augroup syntax
</para>
<para>
au! BufNewFile,BufReadPost *.spec so ~/etc/vim/spec.vim
</para>
<para>
au BufNewFile,BufReadPost *.spec so ~/etc/vim/spec.vim
</para>
<para>
augroup END
</para>
<para>
This statement will instruct VIM to load the syntax file
whenever a file named with a .spec extension is edited. You can
now even customize the colors which VIM uses, if you like, by
editing ~/etc/vim/spec.vim!
</para>
<para>
The VIM editor has hundreds of built-in commands for formatting
text. If necessary, it can even be extended with new commands.
Furthermore, these commands can be defined in FileType plugins,
so that different commands are loaded depending upon the type of
file being edited (just as different syntax matching can be used
depending upon the type of file being edited). Gustavo Niemeyer
has written a spec plugin, pi_spec, which defines various
commands that can be used when working with RPM spec files.
Currently, this plugin can be used to automate maintenance of
the %changelog section of RPM spec files.
</para>
<para>
By default, the spec plugin provides a macro, spec_chglog, which
is mapped to the <LocalLeader>-c key. Normally, the
LocalLeader key in VIM is mapped to "\", a backslash character.
This means you press \c to load the spec_chglog macro. If
desired, you can instead map spec_chglog to a different key by
putting a statement like the following in your ~/.vimrc file.
</para>
<para>
au FileType spec map <buffer> C <Plug>SpecChangelog
</para>
<para>
In this case, that statement would map the macro to the "C" key,
but you can map it to a different key by replacing the "C" in
the statement with whichever key or key combination you prefer.
</para>
<para>
The spec_chglog macro checks the %changelog in the spec file
currently being edited and makes sure that the last entry in
this %changelog was written today and was written by you. If it
was, the macro adds a new item to the entry. If it was not
written today, or was written today, but not by you, the macro
adds an entirely new entry. Optionally, the macro also checks
that the name, version, and release of the package are correct
and will update the release if it is incorrect. In addition, the
macro maps the percent key, %, making it usable in command mode
in VIM to move quickly between sections within a spec file.
</para>
<para>
To help spec_chglog, you can define a few variables in your
~/.vimrc file to customize its behavior. The variable
spec_chglog_format defines what the macro uses for new
%changelog entries. If you do not define this variable, the
macro will ask you for an e-mail address and construct it for
you the first time you use the macro. Alternatively, you can
customize it yourself by adding an entry like the following to
your ~/.vimrc file.
</para>
<para>
let spec_chglog_format = "%a %b %d %Y Your Name
<your at email.address>"
</para>
<para>
The preceding format is what Red Hat's developers use for Red
Hat Linux spec files and results in a %changelog entry that
looks like the following, with the user name and e-mail address
changed to protect the innocent:
</para>
<para>
* Mon Apr 15 2002 Bob Marley <bob at marley.yow>
</para>
<para>
The variables in the spec_chglog_format control the time format
that is used. If you want different time formats in your
%changelog entry, you can replace the variables (using %A
instead of %a would cause the full weekday name, such as
"Monday", to be printed) using the documentation in the
strftime(3) man page as a guideline.
</para>
<para>
By default, the macro will insert new entry items after existing
items. For example, if I already have a %changelog entry for
today that reads as follows:
</para>
<para>
* Mon May 6 2002 Bob Marley <bob at marley.yow>
</para>
<para>
- Updated to newest release
</para>
<para>
Then, using the macro to add a new entry for an additional patch
I added will, by default, result in an entry that reads:
</para>
<para>
* Mon May 6 2002 Bob Marley <bob at marley.yow>
</para>
<para>
- Updated to newest release
</para>
<para>
- Added Solaris compile patch
</para>
<para>
If I want, I can instead have new items inserted before existing
items, so that my second entry instead looks like
</para>
<para>
* Mon May 6 2002 Bob Marley <bob at marley.yow>
</para>
<para>
- Added Solaris compile patch
</para>
<para>
- Updated to newest release
</para>
<para>
To have new items inserted before existing items, simply add the
following line to your ~/.vimrc file:
</para>
<para>
let spec_chglog_prepend = 1
</para>
<para>
Optionally, the macro can track version and release numbers in
the %changelog entries automatically. Adding the line
</para>
<para>
let spec_chglog_release_info = 1
</para>
<para>
results in the first item in every changelog entry automatically
reflecting the version and release, so that my %changelog entry
might instead look like the following:
</para>
<para>
* Mon May 6 2002 Bob Marley <bob at marley.yow>
</para>
<para>
+ httpd-2.0.36-2
</para>
<para>
- Updated to newest release
</para>
<para>
- Added Solaris compile patch
</para>
<para>
If this feature is enabled, the macro automatically checks the
version and release information to make sure that they have
increased. If they haven't, it will offer to update them for
you. Add the following line to your ~/.vimrc file to disable
this feature, if necessary.
</para>
<para>
let spec_chglog_never_increase_release = 1
</para>
<para>
This spec plugin ships with newer versions of VIM. Both it and
the VIM spec syntax highlighting extensions can be very useful
for speeding spec file editing and debugging, and are well worth
trying out if you are a VIM user.
</para>
<para>
Cross Reference
</para>
<para>
You can find out more about vim at www.vim.org.
</para>
</sect2>
<sect2>
<title>Adding functions with emacs rpm-spec-mode</title>
<para>
Of course, not everyone in the world uses VIM. Another commonly
used editor is the emacs editor originally developed by Richard
M. Stallman. Unlike vi, emacs is not considered an essential
Unix component and is not always found installed on a Unix
system, although it is bundled with just about every Linux
distribution.
</para>
<para>
Over the years, two major emacs variants have emerged. GNU Emacs
is produced by the Free Software Foundation and can be
downloaded from www.gnu.org/software/emacs/emacs.html. XEmacs is
based on GNU Emacs and is available from www.xemacs.org.
Historically, the two differed in their user interfaces (XEmacs,
as the name suggests, had an X Window interface, though GNU
Emacs has one as well these days) and in some technical details
of how they operated. Both are freely available under the terms
of the GNU GPL, so you can download and try either or both if
they are not already on your system.
</para>
<para>
Cross Reference
</para>
<para>
See Appendix G for more on the GNU GPL, or General Public
License.
</para>
<para>
Red Hat Linux includes RPMs of both GNU Emacs and XEmacs as part
of the distribution, and most other Linux distributions will
include one or both as well.
</para>
<para>
Like VIM, both GNU Emacs and XEmacs support syntax highlighting.
They are also both extensible, having the ability to load mode
files that add new commands and functions. Stig Bjørlykke has
written a mode, rpm-spec-mode.el, which works with both GNU
Emacs and with XEmacs to add many functions, making it easier to
use when editing RPM spec files. Red Hat Linux includes and
enables this mode in both GNU Emacs and XEmacs, as do many other
Linux distributions.
</para>
<para>
Cross Reference
</para>
<para>
You can download this emacs mode from
http://tihlde.org/~stigb/rpm-spec-mode.el.
</para>
<para>
After downloading, you will need to put the following lines in
your ~/.emacs init files (for GNU Emacs) or ~/.xemacs init files
(for XEmacs) to instruct emacs to load rpm-spec-mode whenever a
file with a .spec extension is being edited:
</para>
<para>
(autoload 'rpm-spec-mode "rpm-spec-mode.el" "RPM spec mode." t)
</para>
<para>
(setq auto-mode-alist (append '(("\\.spec" . rpm-spec-mode))
auto-mode-alist))
</para>
<para/>
<para>
Once installed, rpm-spec-mode will provide emacs with additional
support for editing RPM spec files. Figure 13-1 shows this mode
in GNU Emacs.
</para>
<para>
54965-0 Fg1301.tiff here; needs to be cropped to just the
central window
</para>
<para>
Figure 13-1: Gnu Emacs using rpm-spec-mode
</para>
<para>
Figure 13-2 shows this mode in XEmacs.
</para>
<para>
54965-0 Fg1302.tiff here; needs to be cropped to just the
central window
</para>
<para>
Figure 13-2: XEmacs using rpm-spec-mode
</para>
<para>
With this mode, emacs can do syntax highlighting of spec files,
just like VIM. The mode file rpm-spec-mode.el contains the emacs
instructions that specify what should be highlighted and what
colors should be used for highlighting.
</para>
<para>
Tip
</para>
<para>
If you do not see syntax highlighting when you edit a spec file,
your emacs session may or may not be currently configured to do
syntax highlighting. First, make sure that the status bar at the
bottom of your emacs window says (RPM-SPEC), indicating that
rpm-spec-mode is being used. If it doesn't, double-check the
rpm-spec-mode installation instructions. If the status bar does
indicate that you are using rpm-spec-mode, also double-check
that syntax highlighting (which, in emacs, is a global
configuration option) has been enabled. In both GNU Emacs and
XEmacs, the Options menu has a Syntax Highlighting option that
must be enabled before emacs will colorize spec file syntactic
structures.
</para>
<para>
In addition to providing syntax colorization, rpm-spec-mode adds
a variety of new functions to emacs that can be used to speed
the process of creating or editing RPM spec files. These new
functions appear on the RPM-Spec menu that is added to emacs by
rpm-spec-mode. Many of the functions are similar to the
functions added to VIM by the spec_chglog macro. Navigation
functions to move quickly through a spec file are provided, so
that Ctrl+C, Ctrl+N (press Ctrl+C followed by Ctrl+N) will move
the cursor to the next major section of the spec file, while
Ctrl+C, Ctrl+P will move the cursor to the prior major section
of the spec file. Similarly, macros are also defined to
increment the release tag (Ctrl+C, R) and the very handy option
to add new %changelog entries (Ctrl+C, E). Like the VIM macros
for adding %changelog entries, the rpm-spec-mode command checks
to see if an entry already exists for today. If not, it adds a
new entry, but if so, it just adds a new item to the existing
entry. For %changelog entries to have the correct e-mail
address, the emacs variable user-mail-address must be set
correctly. If it is not set on your system, you can add the
following line to your emacs initialization files:
</para>
<para>
(setq user-mail-address "your at email.address")
</para>
<para>
In addition to these basic functions, rpm-spec-mode offers more
advanced spec file creation support. Opening a new buffer in
emacs for a spec file that does not already exist automatically
generates a skeleton spec file.
</para>
<para>
To further speed things up, emacs offers a number of macros for
the main tasks in writing an RPM spec file. Table 13-1 lists
these macros.
</para>
<para>
Table 13-1Macro commands for The RPM SPEC MODE IN EMacs
</para>
<informaltable frame="all">
<tgroup cols="2">
<tbody>
<row>
<entry>
<para>
Command
</para>
</entry>
<entry>
<para>
Function
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Tab
</para>
</entry>
<entry>
<para>
Adds a new tag to the spec file
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+F F
</para>
</entry>
<entry>
<para>
Adds a new file to the %files section
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+F C
</para>
</entry>
<entry>
<para>
Adds a new configuration file to the %files section
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+F D
</para>
</entry>
<entry>
<para>
Adds a new documentation file to the %files section
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+F G
</para>
</entry>
<entry>
<para>
Adds a new ghost file to the %files section
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+D D
</para>
</entry>
<entry>
<para>
Adds a new directory to the %files section
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+D O
</para>
</entry>
<entry>
<para>
Adds a new documentation directory to the %files
section
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+C U
</para>
</entry>
<entry>
<para>
Changes the umask in %defattr entries in %files
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+C O
</para>
</entry>
<entry>
<para>
Changes the owner in %defattr entries in %files
</para>
</entry>
</row>
<row>
<entry>
<para>
Ctrl+C Ctrl+C G
</para>
</entry>
<entry>
<para>
Changes the group in %defattr entries in %files
</para>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>
Furthermore, rpm-spec-mode even adds macros to emacs that can be
used to build RPMs from spec files without even having to exit
emacs! Since the process of constructing spec files is often
iterative (make new spec, build RPM from spec, find mistake,
edit spec, build RPM from spec, find mistake, and so on), this
capability of emacs to be used as an IDE for RPM package
generation is extremely useful. Basic macros exist to do
complete builds (Ctrl+C B to build a binary package, Ctrl+C S to
build a source package, and Ctrl+C A to build both). Macros can
also be used to execute various intermediate steps, such as the
%prep stage (Ctrl+C P), the %build stage (Ctrl+C C), or the
%install stage (Ctrl+C I). Various options of the build process
can also be controlled, such as GPG-signing of generated
packages.
</para>
<para>
If you are a user of GNU Emacs or XEmacs, you should definitely
take the time to learn to use rpm-spec-mode. Being able to build
packages from within the editor where you are editing the spec
file that builds those packages is a great productivity gain for
many people.
</para>
</sect2>
<sect2>
<title>Validating and debugging spec files with rpmlint</title>
<para>
Both VIM and emacs extensions help with the process of initially
creating spec files and with the maintenance of existing RPM
spec files. After a spec file has been created, and RPMs have
been created using that spec, the binary RPMs generated from the
spec can be validated using the rpmlint command. The name
rpmlint comes from lint, the traditional Unix utility that can
"sanity-check" C source code, looking for certain classes of
common C coding mistakes. The idea behind rpmlint is similar; it
processes binary RPMs, checking for certain common mistakes made
by RPM packagers.
</para>
<para>
The rpmlint command currently ships with a wide variety of
checks and is written using a modular interface so that
additional checks can easily be added if needed. Currently,
rpmlint can check that all binary files in the package are
correct (making sure that a .noarch.rpm package does not contain
binary files, that no binaries are being installed in /etc, that
the binary file types in the package are appropriate for the
package architecture, that shared libraries are configured
correctly, and that all executables are stripped). It can also
check the validity of files marked as configuration files in the
RPM (ensuring that configuration files are only being installed
in /etc, not in /usr) and that the package file complies with
the distribution's policies for packages (checking things such
as the compression of man pages and Info pages and the
correctness of vendor and distribution fields in the package
header).
</para>
<para>
In addition, rpmlint performs a variety of checks to ensure that
the package complies with the Filesystem Hierarchy Standard
(verifying that files are installed in their standard locations
on the system), the Linux Standards Base (verifying that
package-file naming is LSB-compliant) and that files have
correct ownerships and permissions. Init scripts are
double-checked (for packages that have init scripts) to ensure
that the basic structure of the init script is correct and that
appropriate %post and %preun configuration directives are being
run to configure the init script on the system. %post, %pre, and
%preun scripts are also double-checked (ensuring that only valid
interpreters are specified for scripts and that scripts are
written in valid syntax). The validity of the package itself is
also checked in various ways (ensuring that the package is
GPG-signed, that the package's source RPM is correctly prepared,
that the package spec file uses correct syntax, and that all
tags used in the package header are valid).
</para>
<para>
Cross Reference
</para>
<para>
To find out more about the Filesystem Hierarchy Standard, see
www.pathname.com/fhs/. To find out more about the Linux
Standards Base, see www.linuxbase.org.
</para>
<para>
Download rpmlint from www.lepied.com/rpmlint. It is written
entirely in Python, so a Python interpreter is necessary to run
it.
</para>
<para>
Once installed, rpmlint can be configured on a system-wide
basis, using the /etc/rpmlint/config file, or on a per-user
basis, using the $HOME/.rpmlintrc file. This file can specify
checks to perform, check output that should be ignored, and
configuration options. Configuration options can be specified,
listing what entries are valid for various fields in the RPM
header, such as the Vendor and Packager fields. By default, Red
Hat Linux ships with this configuration file set to validate
packages to make sure they are suitable for Red Hat Linux; if
packaging for a different distribution, this file might need to
be modified.
</para>
<para>
Once rpmlint has been installed and configured, it can be run
against RPMs. For example, rpmlint helps with creating packages,
such as tin (a popular Usenet client) for Red Hat Linux, since
it is not included with the distribution. After preparing a tin
spec file, then building RPMs from that file, you can typically
double-check them using rpmlint.
</para>
<para>
For example, when running rpmlint on a source RPM, youâll see
output like the following:
</para>
<para>
$ rpmlint tin-1.5.12-1.src.rpm
</para>
<para>
E: tin no-packager-tag
</para>
<para>
W: tin invalid-license distributable
</para>
<para>
W: tin no-url-tag
</para>
<para>
W: tin strange-permission tin-1.5.12.tar.bz2 0664
</para>
<para>
W: tin obsolete-tag Copyright
</para>
<para>
$
</para>
<para>
For the most part, this package looks fine according to the
rpmlint output. The permissions on the tin source code can be
changed (0644 is the "preferred" permissions), and you might
want to change my spec file to use the License tag instead of
the now-obsolete Copyright tag. Similarly, you might want to add
a URL tag to the package to point to the URL for the software.
</para>
<para>
When running rpmlint on a binary RPM, youâll see output like
the following:
</para>
<para>
$ rpmlint tin-1.5.12-1.i386.rpm
</para>
<para>
W: tin invalid-vendor None
</para>
<para>
W: tin invalid-distribution None
</para>
<para>
E: tin no-packager-tag
</para>
<para>
W: tin invalid-license distributable
</para>
<para>
W: tin no-url-tag
</para>
<para>
$
</para>
<para>
With this output, the binary package looks fine. You should set
a I donât bother setting a vendor, distribution, and packager
but you can ignore those warnings. Similarly, rpmlint warns
because it does not recognize the license type used,
"distributable". You can fix this, you can ignore this, or you
can modify /etc/rpmlint/config so that rpmlint recognizes
"distributable" as a valid license.
</para>
<para>
The sorts of validity checks that rpmlint can do make it
valuable for ensuring the quality and consistency of RPMs. Most
RPM-based Linux distributions validate their entire distribution
using rpmlint. Using it for packages you prepare is a good idea
as well.
</para>
</sect2>
<sect2>
<title>Generating the %files section with RUST</title>
<para>
For the most part, maintaining RPM spec files is relatively
straightforward. Creating spec files from scratch, however, can
be a little bit more challenging. Tools like rpm-spec-mode for
emacs can help with the process, generating skeleton spec file
templates that can be filled in, but these sorts of tools do not
address the step that most new RPM packagers seem to find most
difficult: generating the %files section. Creating a complete,
accurate list of all needed files supplied by an application can
be difficult, particularly when it is an application with which
you are unfamiliar. Most software supports installation to a
temporary location; if the software you are packaging allows
this, generation of %files is (almost) as simple as using
BuildRoot to install the application to a temporary directory,
then running an ls -lR command in that subdirectory to see all
the installed files and directories. Even then, though, the
output from ls -lR must be cleaned up and converted into %files
format for adding to the spec file. All of this takes time.
</para>
<para>
A couple of tools exist to reduce the amount of work needed for
this stage of the process, automating the generation of the
%files section of spec files. The most sophisticated of these
toolsets is RUST.
</para>
<para>
Cross Reference
</para>
<para>
Download RUST from www.rusthq.com.
</para>
<para>
RUST consists of two tools: crust and rust. The crust command
provides a command-line tool that can create a chroot() jail, in
which software can be built and installed, and then
automatically generate a spec file that documents the files that
were installed. This not only eliminates the need to generate a
%files section for a spec file manually but also removes the
need to modify software to support installation to a temporary
location using BuildRoot, a sometimes difficult task.
</para>
<para>
The rust command provides a graphical front end to the crust
command, as shown in Figure 13-3.
</para>
<para>
54965-0 Fg1303.tiff here
</para>
<para>
Figure 13-3: rust, a drag-and-drop spec file generator
</para>
<para>
The rust command provides a graphical interface that can be used
to control crust and supports drag-and-drop creation of spec
files. In the rust interface, two file trees are displayed. The
left-hand tree displays the local file system, while the
right-hand tree displays the file tree inside the crust chroot()
jail. Files that should be packaged together can just be dragged
from their current locations on the system (displayed in the
left-hand tree) to their final destinations in the right-hand
tree. You can then click the makeRPM choice to generate an RPM
containing those files. Although not terribly useful for
packages being generated from source code, this feature can
greatly simplify creation of RPMs of applications that are only
supplied in binary format (such as the Linux Adobe Acrobat
reader).
</para>
<para>
RUST's rust application can be useful in some circumstances
(providing new developers a graphical tool that can be used to
generate binary RPMs), and crust is more generally useful for
packaging difficult-to-package software that needs to be built
and installed in a chroot() jail. Unfortunately, development of
RUST appears to have stopped, so extension of RUST to become a
more generally useful IDE for RPM generation is not likely to
happen. However, the project is licensed under the GNU GPL
(Appendix G), so it might be resumed by another developer or
team of developers.
</para>
</sect2>
<sect2>
<title>setup.sh and MakeRPM.pl</title>
<para>
Other tools that have been developed to simplify the process of
creating an RPM spec file take an entirely different approach.
Tools such as setup.sh, available from
www.mmedia.is/~bre/programs/setup.sh, are intended to function
as wrappers around the existing build commands (./configure and
make) for software. These types of tools take the approach of
using the standard build tools for software (since those tools
must always be used to build the software, whether using RPM or
compiling the software from a source tarball) and capturing the
output to generate an RPM spec file automatically.
</para>
<para>
The MakeRPM.pl Perl script, available from
www.perl.com/CPAN/modules/by-authors/id/JWIED, is another
example of such an approach. MakeRPM.pl is a more specialized
tool than setup.sh, as MakeRPM.pl is intended only for producing
RPMs from Perl modules packaged in CPAN (www.cpan.org). It is
implemented as a wrapper around the standard commands (perl
Makefile.PL ; make ; make test ; make install) used to install
Perl CPAN software.
</para>
<para>
MakeRPM.pl actually works quite well for its intended
purpose at mdproducing packages of CPAN modules. The setup.sh
script is currently viewable mainly as a proof of concept,
rather than being a generally universal automatic spec file
generator. In the future, when spec files are likely to be
representable using a formal closed-syntax grammar, it is
possible that more generalized spec file generation tools will
be developed. Until that time, however, some of the previously
mentioned tools, particularly the VIM and emacs extensions, can
provide assistance when manually generating spec files.
</para>
<para>
Cross-reference
</para>
<para>
For more discussion of the future of RPM, you can turn to
Chapter 22.
</para>
</sect2>
<sect2>
<title>Manipulating Package Files with rpm2cpio</title>
<para>
Normally, RPM packagers are concerned with taking source code or
binary files, and producing an RPM that contains those files and
can be used to install them on end-users' systems. Sometimes,
packagers and end users find themselves in the opposite
position, that of having a source or binary RPM package file and
needing to extract its contents. An RPM can always be installed
to access its contents (either source code, patches, and a spec
file which get put under %_topdir for a source RPM, or software
which gets put in system directories for a binary RPM), but that
is often overkill. I frequently want to extract a single patch
file, or the spec file, from a source RPM, but I don't really
need to install the entire source RPM. Similarly, people often
want to extract the contents of RPMs on systems that do not come
with RPM, such as Solaris.
</para>
<para>
Fortunately, tools are available that can process RPM package
files into a format from which their content can be extracted.
Structurally speaking, RPM package files are compressed cpio
archives that have additional binary data added to the beginning
containing various meta-data about the package (specifying its
architecture and OS, for example), a GPG signature if the
package is signed, and so forth. If this binary data is removed
from the beginning of the RPM package file, the remainder is a
System V Release 4-style cpio file that can be manipulated using
any reasonably complete cpio command. Several different tools,
each sporting the name rpm2cpio, are available which can do this
binary data removal, converting an RPM package file into a
standard cpio archive.
</para>
<para>
RPM ships with an rpm2cpio utility that can be used to convert
RPM package files to cpio files. (Chapter 3 introduces the
rpm2cpio utility.) For example, if you have a source RPM package
file and want to extract its files without having to install it,
you can process it through rpm2cpio. The rpm2cpio command takes
as input an RPM package file, and produces a cpio file on
standard output. For example, to redirect the output to a file,
use a command like the following:
</para>
<para>
$ rpm2cpio fluxbox-0.1.8-2.src.rpm > fluxbox-0.1.8-2.cpio
</para>
<para>
$
</para>
<para>
This command creates a cpio archive from the package. You can
later use cpio commands on the output file. You can also pipe
the output of rpm2cpio through the cpio command:
</para>
<para>
$ rpm2cpio fluxbox-0.1.8-2.src.rpm | cpio -i -d
</para>
<para>
656 blocks
</para>
<para>
$
</para>
<para>
This command extracts the contents of the package.
</para>
<para>
This rpm2cpio command is bundled with RPM and is installed on
most RPM-based Linux distributions, including Red Hat Linux.
However, it is less useful on systems that do not come with RPM,
such as Solaris. This "standard" implementation of rpm2cpio is
written in C, and so must be compiled before it can be used.
Since most commercial Unix systems do not come with a C compiler
by default (unlike Linux and other free Unixes, such as the BSD
operating systems), compiling this rpm2cpio code can be a major
undertaking.
</para>
<para>
Fortunately, rpm2cpio implementations are also available in a
couple of other languages, in more easy-to-install formats for
other operating sytsems, including as a Bourne shell script or a
Perl script. The Bourne shell syntax should work on any
reasonably modern Unix system (and even a few non-Unix systems;
it also works on Microsoft Windows under cygwin, for example).
The script in Listing 13-1should be saved to a file named
rpm2cpio.sh, marked executable, and copied to a directory in
your path.
</para>
<para>
Listing 13-1: rpm2cpio as a Bourne Shell script
</para>
<para>
#!/bin/sh
</para>
<para/>
<para>
pkg=$1
</para>
<para>
if [ "$pkg" = "" -o ! -e "$pkg" ]; then
</para>
<para>
echo "no package supplied" 1>&2
</para>
<para>
exit 1
</para>
<para>
fi
</para>
<para/>
<para>
leadsize=96
</para>
<para>
o=`expr $leadsize + 8`
</para>
<para>
set `od -j $o -N 8 -t u1 $pkg`
</para>
<para>
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
</para>
<para>
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
</para>
<para>
# echo "sig il: $il dl: $dl"
</para>
<para/>
<para>
sigsize=`expr 8 + 16 \* $il + $dl`
</para>
<para>
o=`expr $o + $sigsize + \( 8 - \( $sigsize \% 8 \) \) \% 8 + 8`
</para>
<para>
set `od -j $o -N 8 -t u1 $pkg`
</para>
<para>
il=`expr 256 \* \( 256 \* \( 256 \* $2 + $3 \) + $4 \) + $5`
</para>
<para>
dl=`expr 256 \* \( 256 \* \( 256 \* $6 + $7 \) + $8 \) + $9`
</para>
<para>
# echo "hdr il: $il dl: $dl"
</para>
<para/>
<para>
hdrsize=`expr 8 + 16 \* $il + $dl`
</para>
<para>
o=`expr $o + $hdrsize`
</para>
<para/>
<para>
dd if=$pkg ibs=$o skip=1 2>/dev/null | gunzip
</para>
<para>
After you have marked this file as executable and placed it in
your command path, you can use the script just like the C
language implementation of rpm2cpio. This script also takes an
RPM package file as input and produces a cpio file on standard
output, and so should be used in conjunction with redirection or
a pipe:
</para>
<para>
$ rpm2cpio.sh fluxbox-0.1.8-2.src.rpm | cpio -i -d
</para>
<para>
656 blocks
</para>
<para>
$
</para>
<para>
In this case, I piped the output to cpio, directly extracting
it. I could have redirected the output of rpm2cpio.sh to a file
instead.
</para>
<para>
In addition to the Bourne shell implementation of rpm2cpio, a
version has been written in Perl by Roger Espel Llima. The Perl
rpm2cpio implementation should work on any system that has a
reasonably modern Perl interpreter. To use this version of
rpm2cpio, the script in Listing 13-2 should be saved to a file
named rpm2cpio.pl, marked executable, and copied to a directory
in your path.
</para>
<para>
Listing 13-2:The Perl version of rpm2cpio, rpm2cpio.pl
</para>
<para>
#!/usr/bin/perl
</para>
<para/>
<para>
# Copyright (C) 1997,1998,1999, Roger Espel Llima
</para>
<para>
#
</para>
<para>
# Permission is hereby granted, free of charge, to any person
obtaining a copy
</para>
<para>
# of this software and any associated documentation files (the
"Software"), to
</para>
<para>
# deal in the Software without restriction, including without
limitation the
</para>
<para>
# rights to use, copy, modify, merge, publish, distribute,
sublicense,
</para>
<para>
# and/or sell copies of the Software, and to permit persons to
whom the
</para>
<para>
# Software is furnished to do so, subject to the following
conditions:
</para>
<para>
#
</para>
<para>
# The above copyright notice and this permission notice shall be
included in
</para>
<para>
# all copies or substantial portions of the Software.
</para>
<para>
#
</para>
<para>
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR
</para>
<para>
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
</para>
<para>
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE
</para>
<para>
# SOFTWARE'S COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER
</para>
<para>
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM,
</para>
<para>
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
</para>
<para>
# THE SOFTWARE
</para>
<para/>
<para>
# (whew, that's done!)
</para>
<para/>
<para>
# why does the world need another rpm2cpio? because the existing
one
</para>
<para>
# won't build unless you have half a ton of things that aren't
really
</para>
<para>
# required for it, since it uses the same library used to
extract RPM's.
</para>
<para>
# in particular, it won't build on the HPsUX box i'm on.
</para>
<para/>
<para>
# sw 2002-Mar-6 Don't slurp the whole file
</para>
<para/>
<para>
# add a path if desired
</para>
<para>
$gzip = "gzip";
</para>
<para/>
<para>
sub printhelp {
</para>
<para>
print <<HERE;
</para>
<para>
rpm2cpio, perl version by orabidoo <odar\@pobox.com> +sw
</para>
<para>
dumps the contents to stdout as a cpio archive
</para>
<para/>
<para>
use: rpm2cpio [file.rpm] > file.cpio
</para>
<para/>
<para>
Here's how to use cpio:
</para>
<para>
list of contents: cpio -t -i < /file/name
</para>
<para>
extract files: cpio -d -i < /file/name
</para>
<para>
HERE
</para>
<para/>
<para>
exit 0;
</para>
<para>
}
</para>
<para/>
<para>
if ($#ARGV == -1) {
</para>
<para>
printhelp if -t STDIN;
</para>
<para>
$f = "STDIN";
</para>
<para>
} elsif ($#ARGV == 0) {
</para>
<para>
open(F, "< $ARGV[0]") or die "Can't read file $ARGV[0]\n";
</para>
<para>
$f = 'F';
</para>
<para>
} else {
</para>
<para>
printhelp;
</para>
<para>
}
</para>
<para/>
<para>
printhelp if -t STDOUT;
</para>
<para/>
<para>
# gobble the file up
</para>
<para>
##undef $/;
</para>
<para>
##$|=1;
</para>
<para>
##$rpm = <$f>;
</para>
<para>
##close ($f);
</para>
<para/>
<para>
read $f,$rpm,96;
</para>
<para/>
<para>
($magic, $major, $minor, $crap) = unpack("NCC C90", $rpm);
</para>
<para/>
<para>
die "Not an RPM\n" if $magic != 0xedabeedb;
</para>
<para>
die "Not a version 3 or 4 RPM\n" if $major != 3 &&
$major != 4;
</para>
<para/>
<para>
##$rpm = substr($rpm, 96);
</para>
<para/>
<para>
while (!eof($f)) {
</para>
<para>
$pos = tell($f);
</para>
<para>
read $f,$rpm,16;
</para>
<para>
$smagic = unpack("n", $rpm);
</para>
<para>
last if $smagic eq 0x1f8b;
</para>
<para>
# Turns out that every header except the start of the gzip one
is
</para>
<para>
# padded to an 8 bytes boundary.
</para>
<para>
if ($pos & 0x7) {
</para>
<para>
$pos += 7;
</para>
<para>
$pos &= ~0x7;# Round to 8 byte boundary
</para>
<para>
seek $f, $pos, 0;
</para>
<para>
read $f,$rpm,16;
</para>
<para>
}
</para>
<para>
($magic, $crap, $sections, $bytes) = unpack("N4", $rpm);
</para>
<para>
die "Error: header not recognized\n" if $magic != 0x8eade801;
</para>
<para>
$pos += 16;# for header
</para>
<para>
$pos += 16 * $sections;
</para>
<para>
$pos += $bytes;
</para>
<para>
seek $f, $pos, 0;
</para>
<para>
}
</para>
<para/>
<para>
if (eof($f)) {
</para>
<para>
die "bogus RPM\n";
</para>
<para>
}
</para>
<para/>
<para>
open(ZCAT, "|gzip -cd") || die "can't pipe to gzip\n";
</para>
<para>
print STDERR "CPIO archive found!\n";
</para>
<para/>
<para>
print ZCAT $rpm;
</para>
<para/>
<para>
while (read($f, ($_=''), 16384) > 0) {
</para>
<para>
print ZCAT;
</para>
<para>
}
</para>
<para/>
<para>
close ZCAT;
</para>
<para>
After set up, rpm2cpio.pl works much like the C and Bourne shell
versions, so the following command can be used to generate a
cpio archive from an RPM package file:
</para>
<para>
$ rpm2cpio.pl fluxbox-0.1.8-2.src.rpm | cpio -i -d
</para>
<para>
CPIO archive found!
</para>
<para>
656 blocks
</para>
<para>
$
</para>
<para/>
<para>
Depending upon the system you are on, one or more of these three
rpm2cpio programs should work. All three are useful any time you
want to extract a file or files from an RPM package file but do
not actually need to install the RPM.
</para>
</sect2>
</sect1>
<sect1>
<title>Summary</title>
<para>
Creating RPM spec files and maintaining those files can be a
difficult chore. A number of tools and add-ons for text editors
have sprung up to help make this less of a chore.
</para>
<para>
Users of the two most common Linux text editors, vi and emacs, can
use add-ons that understand the RPM spec file syntax. These
add-ons help reduce errors and, though the use of macros, can
speed development of spec files by automating some of the tasks.
</para>
<para>
The RUST tool provides a graphical interface for creating spec
files that can simplify a lot of the work normally required.
</para>
<para>
Once youâve created an RPM package, you can use the rpmlint
command to flag missing, incomplete, or incorrect elements in your
RPMs.
</para>
<para>
Another tool, called rpm2cpio in its various incarnations, allows
you to extract files from an RPM package by taking advantage of
the fact that RPM files use the cpio format internally. The
rpm2cpio tools can output RPM data into the cpio format directly;
you can then pipe the output to the cpio command to extract.
</para>
<para>
After all this help in making RPMs and spec files, the next
chapter covers a set of best-practice guidelines to help avoid
problems when making your RPMs.
</para>
</sect1>
</chapter>
<!--
Local variables:
mode: xml
sgml-parent-document:("rpm-guide-en.xml" "book" "chapter")
fill-column: 72
End:
-->
More information about the Fedora-docs-commits
mailing list