United States (change)
Shortcuts: Downloads Fedora Red Hat Network
A few months ago, we gave you a quick look at basic RPM commands. But how is an RPM built? It all begins with the SPEC file. A what file? We'll explain all that, and maybe a bit more. The package information tags, such as the name of the package, and the build sections; such as the commands to compile the software.
The following sections summarize the spec file syntax.
The package information tags contain most of the header tags that you can query
with the rpm command. First and foremost, this includes a name.
The name-epoch-version-release tags, which form the NEVR used to identify
packages, should all appear in your spec file, although you can skip the Epoch
tag.
Name: name
# Epoch: 1 Version: version_number
Release: package_release_number
The optional Epoch tag provides an ordering for the version numbers
(replacing the deprecated Serial tag). Use this tag if RPM cannot
figure out the ordering of which release comes after another.
Epoch: 42
A number of tags allow you to define who made the package and under what conditions has the package been released:
Vendor: name_of_vendor
URL: URL_to_package_home Copyright: package_copyright_message Distribution: Linux_or_product_distribution Packager: John Q. Smith <john.smith@somecompany.yow>Group: group_for_categorizing_package
Use the Group tag to help users categorize your package.
The Icon tag allows you to provide a desktop icon for the package:
Icon: filename.xpm
A one-line summary is essential to tell users what your package is for:
Summary: one_line_description_of_package
You should also include a longer description section, marked by %description:
%description
Tcsh is an enhanced but completely compatible version of csh, the C shell. Tcsh is a command language interpreter which can be used both as an interactive login shell and as a shell script command processor. Tcsh includes a command line editor, programmable word completion, spelling correction, a history mechanism, job control and a C language
like syntax.
In the description section, blank lines indicate paragraphs. Lines that start with a space are not formatted.
To help document your work, you can include comments (to yourself and others
reading the spec file). Any line starting with a hash character, #,
holds a comment. RPM will ignore comments.
# This is a comment.
In spec files, comments are used mostly to help explain your syntax choices to yourself should you view the spec file later.
NoteAvoid using percent signs (
%) in comments. They may get interpreted as RPM macros. See Chapter 10 for details.
The BuildArchitectures tag names the architectures that a binary
RPM will run on. See Chapter 21 for a description of the architecture settings.
A special value of noarch indicates a package that is not dependent
on a particular architecture, such as a Perl or Python script.
The BuildPreReq tag lists any prerequisites for building. For
example:
BuildPreReq: ncurses-devel
The Buildroot tag names the temporary directory in which to build
the package. For example:
Buildroot: %{_tmppath}/%{name}-root
Dependency tags define all the dependencies for the package, as described in Chapter 6.
For each dependency, you can specify a capability name alone. For example:
Provides: capability_name
You can also provide a particular version number or indicate that your package has a dependency on a version larger or smaller than a given number. For example:
Requires: capability_name >= version_number
Requires: capability_name <= version_number Requires: capability_name > version_number Requires: capability_name < version_number Requires: capability_name == version_numberRequires: capability_name = version_number
The ==and = act the same for dependencies. Both check
for a version equal to the given number. You can provide multiple items, separated
by commas. For example:
Requires: python >= 1.3, perl
For add-on modules for interpreters, especially Perl, you can use the following syntax to define capabilities:
Provides: perl(MIME-Base64)
This example provides the MIME-Base64 add-on Perl module.
You can also use or to specify more than one possibility. For example:
perl(IO-Wrap) == 4.5 or perl(IO-Wrap)-4.5
The Provides, Requires, Obsoletes, and
Conflicts dependency tags all work the same for capability names
and version numbers.
NoteYou can also specify
BuildRequirestags for capabilities necessary to build the package, not to install it. ABuildConflictstag names capabilities that conflict for building, such as a particular version of the gcc C compiler.
The source and patch tags identify the source files used to build the binary package. The patch tags identify any patches used to modify the sources.
If you have more than one of a particular kind of tag, append a number. For example:
Source0: ftp://ftp.uk.linux.org/pub/linux/telnet-%{telnet_version}.tar.gz
Source2: telnet-client.tar.gz Source3: telnet-xinetd Source4: telnet.wmconfig Patch1: telnet-client-cvs.patch Patch5: telnetd-0.17.diff Patch6: telnet-0.17-env.patch Patch7: telnet-0.17-issue.patch Patch8: telnet-0.17-sa-01-49.patch Patch9: telnet-0.17-env-5x.patchPatch10: telnet-0.17-pek.patch
You can define macros in your spec files to help control how the package gets built. The following section describes these macros.
The %define macro allows you to define new macros from within
your spec file. A common usage is to define top-level directories with %define
macros at the top of a spec file and then reference these directories throughout
the file. For example:
%define _bindir /bin
This allows you to change the setting in one place, which is very handy for directory paths used throughout your spec files.
Cross ReferenceSee the section "Defining Macros in Spec Files" in Chapter 21 for more on this subject.
You can use this syntax for other things that may commonly change, such as version numbers. For example:
%define major 2
%define minor 2 %define patchlevel 7Version: %{major}.%{minor}.%{patchlevel}
Table B-1 lists more special macros used within spec files.
|
Macro |
Usage |
|
|
Prints out macro values |
|
|
Prints message to stderr |
|
|
Prints message to stderr and returns BADSPEC |
|
|
Like eval, expands expression |
|
|
Expands file_exp to a file name |
|
|
Defines a global macro |
|
|
Expands patch_exp to a patch file name |
|
|
Expands source_exp to a source file name |
|
|
Toggles the printing of debugging information |
|
|
Tests if file filename is compressed. If so, uncompresses and includes in the given context. If not compressed, calls cat to include file in given context. |
|
|
Undefines the given macro |
|
|
Prints message to stderr |
You can use a special syntax to test for the existence of macros. For example:
%{?macro_to_test: expression}
This syntax tells RPM to expand the expression if macro_to_test
exists, otherwise ignore. A leading exclamation point, !, tests
for the non-existence of a macro:
%{!?macro_to_test: expression}
In this example, if the macro_to_test macro does not exist, then
expand the expression.
The %if macro performs an if test much like scripting languages.
For example:
%if %{old_5x}
%define b5x 1 %undefine b6x%endif
A %else allows you to specify what to do if the test is not successful.
For example:
%if %{old_5x}
%define b5x 1 %undefine b6x %else %define b6x 1 %undefine b5x%endif
Again, use an exclamation point to negate the test. For example:
%if ! %{old_5x}
%define b5x 1 %undefine b6x%endif
You can use a && for an and test. For example:
%if %{old_5x} && %{old_6x}
%{error: You cannot build for .5x and .6x at the same time} %quit%endif
The following macros are built into RPM and can help allow you to place your files in the right locations:
%_prefix /usr
%_exec_prefix %{_prefix} %_bindir %{_exec_prefix}/bin %_sbindir %{_exec_prefix}/sbin %_libexecdir %{_exec_prefix}/libexec %_datadir %{_prefix}/share %_sysconfdir %{_prefix}/etc %_sharedstatedir %{_prefix}/com %_localstatedir %{_prefix}/var %_libdir %{_exec_prefix}/lib %_includedir %{_prefix}/include %_oldincludedir /usr/include %_infodir %{_prefix}/info%_mandir %{_prefix}/man
After providing information about the package, you need to define the build stages, as described in Chapters 10 and 12.
The build preparation section sets the stage for the build. Usually this section
has a %setup command. For example:
%prep
%setup -q
The build section describes how to build the library or application. In most cases, the majority of the instructions are in the Makefile created by the prep section, leaving a build section something like the following:
%build
%configuremake
After building, the installation section holds the commands to install the library or application. For example:
%install
rm -rf %{buildroot}%makeinstall
The clean up section usually calls the make clean command to clean up the built files. For example:
%clean
rm -rf %{buildroot}
RPM packages can run scripts prior to installation with %pre,
and after installation with %post. You can also run scripts prior
to an uninstall with %preun and after an uninstall with %postun.
For example:
%post
/sbin/chkconfig --add ypbind %preun if [ "$1" = 0 ] ; then /sbin/service ypbind stop > /dev/null 2>&1 /sbin/chkconfig --del ypbind fi exit 0 %postun if [ "$1" -ge 1 ]; then /sbin/service ypbind condrestart > /dev/null 2>&1 fiexit 0
The %files tag lists the files your package should install. For
example:
%files
%defattr(-,root,root) /usr/X11R6/bin/xtoolwait/usr/X11R6/man/man1/xtoolwait.*
You should mark configuration and documentation files with %config
and %doc, respectively. For example:
%files
%defattr(-,root,root) /sbin/ypbind %{_mandir}/*/* %config /etc/rc.d/init.d/* %config /etc/yp.conf %dir /var/yp %dir /var/yp/binding%doc README NEWS
You can make a relocatable package by setting up one or more Prefix
tags. For example:
Prefix: /usr
Prefix: /etc
Each file in the %files section must then start with one of the
prefixes you provided. With this, installers can easily relocate the package
with a command like the following:
# rpm --relocate /etc=/usr/etc file_name.rpm
The change log usually appears at the end of a spec file. It holds messages for each significant change. For example:
%changelog
* Fri Jun 21 2002 Bob Marley <marley@redhat.com> - automated rebuild * Tue May 08 2001 Peter Tosh <tosh@redhat.com> 1.3-1- updated to 1.3