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