-->
Page 154
RPM_PACKAGE_VERSION="1.0" RPM_PACKAGE_RELEASE="1" set -x umask 022 echo Executing: %prep cd /usr/src/redhat/BUILD cd /usr/src/redhat/BUILD rm -rf cdplayer-1.0 gzip -dc /usr/src/redhat/SOURCES/cdplayer-1.0.tgz | tar -xvvf - if [ $? -ne 0 ]; then exit $? fi cd cdplayer-1.0 cd /usr/src/redhat/BUILD/cdplayer-1.0 chown -R root.root . chmod -R a+rX,g-w,o-w .
As you can see, this script contains the %prep section from the spec file. The script starts by defining a number of environment variables and then leads into the %prep section. In the spec file used in this build, the %prep section consists of a single %setup macro. In this file, we can see exactly how RPM expands that macro. The remaining files follow the same basic layouta section-defining environment variables, followed by the commands to be executed.
Note that the --test option will only create script files for each build stage, as specified in the command line. For example, if the previous command were changed to
# rpm -bp --test cdplayer-1.0.spec #
only one script file, containing the %prep commands, would be written. In any case, no matter what RPM build command is used, the --test option can let you see exactly what is going to happen during a build.
The --clean option can be used to ensure that the package's build directory tree is removed at the end of a build. Although it can be used with any build stage, it doesn't always make much sense to do so:
# rpm -bp --clean cdplayer-1.0.spec * Package: cdplayer Executing: %prep ... + exit 0 + echo Executing: sweep Executing: sweep + cd /usr/src/redhat/BUILD + rm -rf cdplayer-1.0 + exit 0 #
Page 155
In this example, we see a typical %prep section being executed. The line + echo Executing: sweep indicates the start of --clean's activity. After changing directory into the build directory, RPM issues a recursive delete on the package's top-level directory.
As noted previously, this particular example doesn't make much sense. We're only executing the %prep section, which creates the package's build tree, and using --clean, which removes it! Using --clean with the -bc option isn't very productive either, as the newly built software remains in the build tree. Once again, there would be no remnants left after --clean has done its thing.
Normally, the --clean option is used once the software builds and can be packaged successfully. It is particularly useful when more than one package is to be built, since --clean ensures that the filesystem holding the build area will not fill up with build trees from each package.
Note also that the --clean option only removes the files that reside in the software's build tree. If there are any files that the build creates outside this hierarchy, it will be necessary to write a script for the spec file's %clean section.
The --buildroot option can make two difficult situations much easier:
Let's study the first situation in a bit more detail. Say, for example, that sendmail is to be packaged. In the course of creating a sendmail package, the software must be installed. This would mean that critical sendmail files, such as sendmail.cf and aliases, would be overwritten. Mail handling on the build system would almost certainly be disrupted.
In the second case, it's certainly possible to set permissions such that non-root users can install software, but highly unlikely that any system administrator worth his salt would do so. What can be done to make these situations more tenable?
The --buildroot option is used to instruct RPM to use a directory other than / as a build root. The term build root is a bit misleading, in that the build root is not the root directory under which the software is built. Rather, it is the root directory for the install phase of the build. When a build root is not specified, the software being packaged is installed relative to the build system's root directory /.
However, it's not enough to just specify a build root on the command line. The spec file for the package must be set up to support a build root. If you don't make the necessary changes, this is what you'll see:
Page 156
# rpm -ba --buildroot /tmp/foo cdplayer-1.0.spec Package can not do build prefixes Build failed. #
Chapter 16, "Making a Package That Can Build Anywhere," has complete instructions on the modifications necessary to configure a package to use an alternate build root, as well as methods to permit users to build packages without root access. Assuming that the necessary modifications have been made, here is what the build would look like:
# rpm -ba --buildroot /tmp/foonly cdplayer-1.0.spec * Package: cdplayer Executing: %prep + cd /usr/src/redhat/BUILD ... + exit 0 Executing: %build + cd /usr/src/redhat/BUILD + cd cdplayer-1.0 ... + exit 0 + umask 022 Executing: %install + cd /usr/src/redhat/BUILD + cd cdplayer-1.0 + make ROOT=/tmp/foonly install install -m 755 -o 0 -g 0 -d /tmp/foonly/usr/local/bin/ install -m 755 -o 0 -g 0 cdp /tmp/foonly/usr/local/bin/cdp rm -f /tmp/foonly/usr/local/bin/cdplay ln -s /tmp/foonly/usr/local/bin/cdp /tmp/foonly/usr/local/bin/cdplay install -m 755 -o 0 -g 0 -d /tmp/foonly/usr/local/man/man1/ install -m 755 -o 0 -g 0 cdp.1 /tmp/foonly/usr/local/man/man1/cdp.1 + exit 0 Executing: special doc + cd /usr/src/redhat/BUILD + cd cdplayer-1.0 + DOCDIR=/tmp/foonly//usr/doc/cdplayer-1.0-1 + rm -rf /tmp/foonly//usr/doc/cdplayer-1.0-1 + mkdir -p /tmp/foonly//usr/doc/cdplayer-1.0-1 + cp -ar README /tmp/foonly//usr/doc/cdplayer-1.0-1 + exit 0 Binary Packaging: cdplayer-1.0-1 Finding dependencies... Requires (2): libc.so.5 libncurses.so.2.0 usr/doc/cdplayer-1.0-1 usr/doc/cdplayer-1.0-1/README usr/local/bin/cdp usr/local/bin/cdplay usr/local/man/man1/cdp.1 93 blocks Generating signature: 0 Wrote: /usr/src/redhat/RPMS/i386/cdplayer-1.0-1.i386.rpm + umask 022 + echo Executing: %clean Executing: %clean + cd /usr/src/redhat/BUILD
Page 157
+ cd cdplayer-1.0 + exit 0 Source Packaging: cdplayer-1.0-1 cdplayer-1.0.spec cdplayer-1.0.tgz 82 blocks Generating signature: 0 Wrote: /usr/src/redhat/SRPMS/cdplayer-1.0-1.src.rpm #
As the somewhat edited output shows, the %prep, %build, and %install sections are executed in RPM's normal build directory. However, the --buildroot option comes into play when the make install is done. As we can see, the ROOT variable is set to /tmp/foonly, which was the value following --buildroot on the command line. From that point on, we can see that make substituted the new build root value during the install phase.
The build root is also used when documentation files are installed. The documentation directory cdplayer-1.0-1 is created in /tmp/foonly/usr/doc, and the README file is placed in it.
The only remaining difference that results from using --buildroot is that the files to be included in the binary package are not located relative to the build system's root directory. Instead, they are located relative to the build root /tmp/foonly. The resulting binary and source package files are functionally equivalent to packages built without the use of --buildroot.
12.1.13.1. Using --buildroot Can Bite You!Although the --buildroot option can solve some problems, using a build root can actually be dangerous. How? Consider the following situation:
The end result? Since specifying / as the build root sets $RPM BUILD ROOT to /, that innocuous little rm -rf $RPM BUILD ROOT turns into rm -rf /! A recursive delete, starting at your system's root directory, might not be a total disaster if you catch it quickly, but in either case, you'll be testing your ability to restore from backup (er, you do have backups, don't you?).
The moral of this story is to be very careful when using --buildroot. A good rule of thumb is to always specify a unique build root. For example, instead of specifying /tmp as a build root (and possibly losing your system's directory for holding temporary files), use the path /tmp/mypackage, where the directory mypackage is used only by the package you're building.