From Fedora Project Wiki

(Add information on rpmdev-newspec for creating new spec files; also note the vim version that first included automatic spec file template creation)
(Replace with a deprecation notice and a link to docs.fp.o)
Tag: Replaced
(317 intermediate revisions by 71 users not shown)
Line 1: Line 1:
== Creating Package HOWTO ==
This page describes the basic mechanics of how to create an RPM package specifically for Fedora (such as
{{admon/important|deprecated|As part of documentation move to docs.fp.o, this page has moved to}}
how to create a .spec file).  It also gives some practical warnings about stuff that will or won't work, which may save you hours of time later.
This is ''not'' the list of official package guidelines for Fedora (though it ''should'' be compatible with them).
This doesn't go into depth on some issues, but it does point to other documents that do.  Unlike many RPM Howto documents, this document explains the specifics for Fedora (with lots
of links to Fedora-specific guidelines) and it tends to be
more up-to-date (because it is maintained through the Fedora Wiki).
For example, it warns of the upcoming impacts of the
[ brand-new version of RPM (version 4.4.2.x) going into pre-Fedora-10 rawhide].
If you plan to create an RPM package for the Fedora repository, follow the process for
[[PackageMaintainers/Join|How to join the Fedora Package Collection Maintainers]],
including following the various Fedora guidance.
Nearly all Linux distributions can install and uninstall programs as "packages".
Fedora, and many other Linux distributions, use the "RPM" format for packages.
There are tools that make it easy to create RPM packages. The main task is to write
a ".spec" file that explains to RPM how to build and install the program.
This page describes how to create RPM packages specifically for Fedora, concentrating
on that very important ".spec" file.
== Setting up your system and account ==
Before you create RPM packages on Fedora, you need to install some core
development tools and set up the account(s) you will use.  As root (don't type the "#"!):
  # yum groupinstall "Development Tools"
  # yum install rpmdevtools
You can create a new "dummy user" specifically for
creating rpm packages.  That way, if something goes terribly wrong, the
program or build process can't trash your files, or
send your private files/keys to the world. At the very least,
you should ''never'' create your packages as user root.
You can create a new user named "makerpm" quickly by doing:
  # /usr/sbin/useradd makerpm
Then log in as that special dummy user (makerpm).
Once you're logged in as the user who is creating packages,
create the directory structure in your home directory by executing (don't type the "$"):
  $ rpmdev-setuptree
The "rpmdev-setuptree" program will create an "rpmbuild" directory in your $HOME
directory. Underneath "rpmbuild" are a set of subdirectories
(such as SPECS and BUILD), which you will use for creating your packages.
The "rpmdev-setuptree" also creates an "~/.rpmmacros" file which will cause
rpm and rpmbuild to use them when appropriate.
Once you've set up the user account, you won't normally need
to do these steps again.
== Getting ready to package a particular program ==
If there are special programs that are required to build or run the program you are packaging, install those
other programs and write down what they were (you'll need that information).
To package a program, you ''must'' package pristine (original) sources, along
with the patches and build instructions.
It's generally ''not'' okay to start with pre-compiled code.
Install the file with the original source (usually a .tar.gz file) in the
"~/rpmbuild/SOURCES" directory (of the rpm building user account).
Read through the manual installation instructions for your program;
you're going to be automating this by editing a ".spec" file, so you have
to understand what you're supposed to do first.
It's probably best if you try a "dry run", going through its installation
procedure without trying to do it via RPM first
(that's especially true if you're not familiar with RPM).
Try to reuse what you can.
Obviously, make sure you aren't packaging something that is already packaged;
you can find a list of existing packages in Fedora Package Collection in the [ Fedora Package Database].
Also check the [[PackageMaintainers/InProgressReviewRequests | In Progress Review Requests]] (for packages that are currently being reviewed)
and the [[PackageMaintainers/RetiredPackages | Retired Packages]] list.
Failing that, see if someone has already started to package it for Fedora.
Google for "PROGRAMNAME Fedora rpm" or similar... maybe you can pick up where
they started.
You can use
directly view .spec files (and patches) of any similar packages already in Fedora.
You can download the source RPMs and install them, too;
go to a [ Fedora mirror]'s http or ftp page,
select releases/9/Everything/source/SRPMS
(replace "9" with the Fedora release you want),
and download the source RPMs you want (they end in .src.rpm).
If you followed the directions above, you can install the source RPM
(which places its .spec file into ~/rpmbuild/SPECS and source files in ~/rpmbuild/SOURCES)
by running:
$ rpm -ivh PROGRAMNAME-*.src.rpm
You can also unpack the .src.rpm in a directory using rpm2cpio:
$ mkdir PROGRAMNAME_src_rpm
$ cd PROGRAMNAME_src_rpm
$ rpm2cpio ../PROGRAMNAME-*.src.rpm | cpio -i
''Sometimes'' it's easiest to start with an existing package, and then clean it up for Fedora.
[ RPM Find] may help you find rpm's for non-Fedora systems.
(You can install source RPMs for other systems the same way as for Fedora).
Failing that, you might look at the source package files (not the .deb binary package files)
for [ Ubuntu] or
[ Debian]
(source package files are standard tarballs with a "debian/" subdirectory, possibly
associated with patch files).
If the [ FreeBSD ports collection] has it,
you could
[ download the FreeBSD ports tarball]
and see if their packaging information helps as a starting point.
'''However''', this is sometimes not helpful at all.
Different distributions have different rules, and what they do may be quite
inappropriate for Fedora.
== Creating a spec file ==
You now need to create a ".spec" file in the "~/rpmbuild/SPECS" directory.
You should name it after the program name, e.g., "program.spec", use the archive name or the name advocated by the software author.
=== Creating a blank spec file ===
When you're creating a spec file for the first time, you can create its initial version using emacs or vim (as of 7.1.270-1),
they will automatically create a template for you.  E.G.:
  $ cd ~/rpmbuild/SPECS
  $ vi program.spec
Here's an example of what that template will look like:
Release: 1%{?dist}
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%setup -q
make %{?_smp_mflags}
rm -rf %{buildroot}
make install DESTDIR=%{buildroot}
rm -rf %{buildroot}
You may have $RPM_BUILD_ROOT instead of %{buildroot}; just be consistent.
You may also use the <code>rpmdev-newspec</code> command to create a spec file for you.  <code>rpmdev-newspec</code> can create spec files tailored to various types of packages, in addition to a generic template like the one above.  See <code>/etc/rpmdevtools/spectemplate-*.spec</code> for available types.  For example, to create a new spec file for a python module:
cd ~/rpmbuild/SPECS
rpmdev-newspec python-antigravity
vi python-antigravity.spec
=== An example: eject ===
Here's a simple example, a Fedora 9 package for the "eject" program:
Summary: A program that ejects removable media using software control.
Name: eject
Version: 2.1.5
Release: 11%{dist}
License: GPL
Group: System Environment/Base
Source1: eject.pam
Patch1: eject-2.1.1-verbose.patch
Patch2: eject-timeout.patch
Patch3: eject-2.1.5-opendevice.patch
Patch4: eject-2.1.5-spaces.patch
Patch5: eject-2.1.5-lock.patch
Patch6: eject-2.1.5-umount.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
ExcludeArch: s390 s390x
BuildRequires: gettext
BuildRequires: automake
BuildRequires: autoconf
BuildRequires: libtool
The eject program allows the user to eject removable media (typically
CD-ROMs, floppy disks or Iomega Jaz or Zip disks) using software
control. Eject can also control some multi-disk CD changers and even
some devices' auto-eject features.
Install eject if you'd like to eject removable media using software
%setup -q -n %{name}
%patch1 -p1 -b .versbose
%patch2 -p1 -b .timeout
%patch3 -p0 -b .opendevice
%patch4 -p0 -b .spaces
%patch5 -p0 -b .lock
%patch6 -p1 -b .umount
rm -rf %{buildroot}
make DESTDIR=%{buildroot} install
# pam stuff
install -m 755 -d %{buildroot}/%{_sysconfdir}/pam.d
install -m 644 %{SOURCE1} %{buildroot}/%{_sysconfdir}/pam.d/%{name}
install -m 755 -d %{buildroot}/%{_sysconfdir}/security/console.apps/
echo "FALLBACK=true" > %{buildroot}/%{_sysconfdir}/security/console.apps/%{name}
install -m 755 -d %{buildroot}/%{_sbindir}
pushd %{buildroot}/%{_bindir}
mv eject ../sbin
ln -s consolehelper eject
%find_lang %{name}
rm -rf %{buildroot}
%files -f %{name}.lang
%attr(644,root,root) %{_sysconfdir}/security/console.apps/*
%attr(644,root,root) %{_sysconfdir}/pam.d/*
* Wed Apr 02 2008 Zdenek Prikryl &lt;zprikryl at,; 2.1.5-11
- Added check if device is hotpluggable
- Resolves #438610
You can also use the "BuildRoot:" entry from the template instead, although both are acceptable, the one from the template is the preferred one.
=== Spec file pieces explained ===
The [ RPM Guide, section on creating RPMs],
describes the details of how to fill in a spec file.
The developerWorks series "Packaging software with RPM" [ Part 1], [ Part 2], and [ Part 3] is also handy.
[ Maximum RPM] has the most complete information, but is dated.
You will need to follow the Fedora guidelines, such as the
[[Packaging/NamingGuidelines| Package Naming Guidelines]],
[[Packaging/Guidelines| Packaging Guidelines]], and
[[Packaging/ReviewGuidelines|Package review guidelines]].
You can insert comments with a leading "#" character, but
don't insert potentially-multiline-macros (words beginning with "%") in a comment
(macros are expanded first); if you're commenting out a line, double the percent signs ("%%").  Also, don't use inline comments ("#") on the same line after
a script command.
Here are the major fields/areas that you will need to fill in:
* Name: The (base) name of the package.  It must follow the [[Packaging/NamingGuidelines| Package Naming Guidelines]].  In many cases, this will be in all lower case.  Elsewhere in the spec file, you can refer to the name using the macro %{name} - that way, if the name changes, the new name will be used by those other locations. This name should match the spec file name.
* Version: The upstream version number. See [ Packaging/Naming guidelines - package version] for more information. If the version is non-numeric (contains tags that are not numbers or digits), you may need to include the additional non-numeric characters in the release field. If upstream uses full dates to distinguish versions, consider using version numbers of the form[dd] (so a 2008-05-01 release becomes 8.05). Elsewhere in the spec file, refer to this value as %{version}.
* Release: The initial value of the release should normally be "1%{?dist}".  Then, increment the number every time you release a new package for the same version of software.  If a new version of the software being packaged is released, the version number should be changed to reflect the new software version, and the release number should be reset to 1.  See [ Name Guidelines - package release] for more. [[Packaging/DistTag]] describes the "dist" tag, which isn't required but can be useful. Use %{release} to reuse this value.
* Summary: A brief, one-line summary of the package. Use American English, and ''do not'' end in a period.
* Group: This needs to be a pre-existing group, like "Applications/Engineering"; run "less /usr/share/doc/rpm-*/GROUPS" to see the complete list.  If you create a sub-package "...-doc" with documentation, use the group "Documentation".
* License: Its license; for software, this must be an open source software license.  Use a standard abbreviation, e.g., "GPLv2+".  Try to be specific, e.g., use "GPLv2+" (GPL version 2 or greater) instead of just "GPL" or "GPLv2" where it's true.  See [[Licensing]] and the [[Packaging/LicensingGuidelines| Licensing Guidelines]] for more information.  Call this tag "License"; don't use the older, inaccurately named tag "Copyright".
* URL: The URL for more information about the program, e.g., the project website.  Note: This is NOT where the original source code came from, see "Source" (next!).
* Source0: The URL for the compressed archive containing (original) pristine source code, as upstream released it. "Source" is synonymous with "Source0".  If you give a full URL (and you should), its basename will be used when looking in the SOURCES directory. If possible, embed %{name} and %{version}, so that changes to either will go to the right place.  '''Warning:''' ''Source0:'' and ''URL:'' are different - normally they are both URLs, but the "URL:" entry points to the project website, while the "Source0:" entry points to the actual file containing the source code (and is typically a .tar.gz file).  As noted in the guidelines, "When downloading sources, patches etc, consider using a client that preserves the upstream timestamps. For example wget -N or curl -R. To make the change global for wget, add this to your ~/.wgetrc: timestamping = on, and for curl, add to your ~/.curlrc: -R."  If there is more than one source, name them Source1, Source2, and so on. If you're adding whole new files in addition to the pristine sources, you can list each of them as sources as well, but list them ''after'' the pristine sources. A copy of each of these sources will be included in any source package you create (unless you specially direct otherwise).  See [[Packaging/SourceURL]] for more information on special cases (using revision control, when upstream uses prohibited code, etc.).
* Patch0: The name of the first patch that you will apply to the source code.  If you need to patch the files after they've been uncompressed, you should edit the files, save their differences as a "patch" file in your ~/rpmbuild/SOURCES directory.  Patches should make only one logical change, so it's quite possible to have multiple patch files.
* BuildRoot: This is where files will be "installed" during the "%install" process (which happens after the %build compilation process).  Normally you should just leave this line alone; under the usual Fedora setup, this will be a macro that will create a new special directory under /var/tmp. The upcoming version of RPM will ignore this value, and instead place the build root in "%{_topdir}/BUILDROOT/".
* BuildRequires: A comma-separated list of packages required for building (compiling) the program.  These are ''not'' automatically determined, so you need to include ''everything'' needed to build the program.  There are a few packages that are so common in builds that you don't need to mention them, such as "gcc"; see the [[Packaging/Guidelines| Packaging Guidelines]] for the complete list of the packages you may omit.  You can also specify minimum versions, if necessary, like this: "ocaml >= 3.08". You can have more than one line of BuildRequires (in which case they are all required for building).  If you need file /EGGS, you can get its package by running "rpm -qf /EGGS"; if EGGS is a program, you determine its package quickly by running "rpm -qf `which EGGS`".  Try to specify only the minimal set of packages necessary to properly build the package, since each one will slow down a "mock"-based build (e.g., try to use sed instead of perl if you don't really need perl's abilities).  Watch out: Some applications permanently disable functions if their package isn't detected during the build; in those cases you may need to include those additional packages.
* Requires: A comma-separate list of packages that are required when the program is installed.  Note that the list of packages for ''Requires'' (what's required when running) and ''BuildRequires'' (what's required to build the binary RPM) are independent; a package may be in one list but not the other, or it could be in both.  The "Requires" list is automatically determined by rpm, so normally you don't need to put anything here. But if you want to highlight some specific packages as being required, or require a package that rpm can't detect should be required, then add it here.
* %description - A longer, multi-line description of the program.  Use American English. All lines must be 80 characters or less. "Blank lines are assumed to separate paragraphs. Some graphical user interface installation programs will reformat paragraphs...  (lines that) start with whitespace, such as a space or tab, will be treated as preformatted text and displayed as is, normally with a fixed-width font." (per the [ RPM Guide]).
* %prep - Script commands to "prepare" the program, that is, to uncompress it so that it will be ready for building (compiling).  Typically this is just "%setup -q" or some variation of it; a common variation is "%setup -q -n NAME" if the source file unpacks into NAME. See the "%prep" section below for more.
* %build - Script commands to "build" the program, that is, to compile it and get it ready for installing.  The program should come with instructions on how to do this.  See the "%build" section below for more.
* %check - Script commands to self-test the program. This is run after %build and before %install, so you should place it there if you have this section.  Often it simply contains "make test" or "make check".  This is separated from %build so that people can skip the self-test if they desire.  This isn't documented in many places.
* %install - Script commands to "install" the program.  The commands should copy the files from the "build directory" %{_builddir} (which would be under ~/rpmbuild/BUILD) into the buildroot directory, %{buildroot} (which would normally be under /var/tmp). See the "%install" section below for more.
* %clean - instructions to clean out the build root. Typically:
rm -rf %{buildroot}
* %files - the list of files that will be installed.  See the "%files" section below for more.
* %changelog - Changes in the package.  Use the format example above.
* ExcludeArch: If the package does not successfully compile, build or work on an architecture, then those architectures should be listed in the spec in an ExcludeArch tag.
* You can add sections so that code will run when packages are installed or removed on the real system (as opposed to just running the %install script, which only does a pseudo-install to the build root).  These are called "scriptlets", and they are usually used to update the running system with information from the package.  See the "Scriptlets" section below for more.
Don't use the tags "Packager" or "Vendor".  Don't use "Copyright" - use "License" instead.
Don't create a "relocatable" package - they don't add value in Fedora yet they make things more complicated.
RPM supports subpackages, that is, a single spec file can generate many
binary packages.  For example, if the documentation is very large, you might generate
a separate "-doc" subpackage.
See below for more.
=== %prep section ===
The "%prep" section describes how to unpack the compressed packages so that they can be built.
Typically, this is a set of "%setup" and/or %patch commands, which reference the Source0:, Source1:, etc. lines above.
See the [ Maximum RPM section on %setup and %patch] for more details.
'''Warning:''' In spec files, don't use in-line comments (a "#" comment on the same line after a command), and don't put macros (words beginning with "%") in a comment unless you quote the "%" as "%%".  Macros can cause failures if they are in a comment, because they are always expanded (even when in a comment) and they can expand to multiple lines.  This is true for %prep, %build, and so on.
The new RPM 4.4.2.x series adds two new macros, %{patches} and %{sources}, so you can do things like:
for p in %{patches}; do
These new macros can very useful if you have a large list of patches or sources.
However, keep in mind that using these will make your spec
incompatible with the rpm used in Fedora 9 and earlier, RHEL, and
many other RPM-based distros.
==== %prep section: %setup command ====
The "%setup" command unpacks a source package, and takes several switches.  Normally you should use "-q" (quiet) to prevent setup from babbling about every file it unpacks.  Here are a few switches besides -q:
* -n ''name'': If the name of the rpm is something other than what the Source unpacks to, use this switch to state the ''name'' it unpacks to.  E.G., if the tarball unpacks into a directory MYNAME, use %setup -q -n MYNAME
* -c ''name'': If the tarball doesn't unpack into a single directory, this creates a directory named ''name'' and then unpacks into it.  Useful if you have one of those annoying tarballs that doesn't have a single common subdirectory embedded in it.
There are
[ more %spec options if you are unpacking multiple files], which is primarily useful if you
are creating subpackages (see below).  The key ones are:
| -a number || Only unpack the source directive of the given number, such as –a 0 for source0:, after changing to the directory.
| -b number ||  Only unpack the source directive of the given number, such as –b 0 for source0:, before changing to the directory.
| -D || Do not delete the directory before unpacking.
| -T || Disable the automatic unpacking of the archives.
==== %prep section: %patch commands ====
The "%patch0" command applies patch 0 (similar for 1, 2, etc.).  The normal "-pNUMBER" option applies, which simply passes that argument on to ''patch''. Patch file names often look like "telnet-0.17-env.patch", that is, ''%{name}''-''%{version}''-''patch_purpose''.patch (some people omit -''%{version}''). Patch files are typically the result of a "diff -u"; if you do this from the subdirectory of ~/rpmbuild/BUILD, you won't have to specify a -p level later.  You can use all the normal ways of creating a patch file.  If you're creating a patch file a single file FILENAME, a common way is to copy it to FILENAME.orig, modify it, and then save the results of "diff -u FILENAME.orig FILENAME":
cp X/Y.Z X/Y.Z.orig
vim X/Y.Z
diff -u X/Y.Z.orig X/Y.Z > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
If you're going to edit many files, one easy method is to copy the whole subdirectory underneath BUILD, and then do subdirectory diffs; once you're in BUILD/whatever, you can:
cp -pr . ../PACKAGENAME.orig
... many edits ...
diff -u . ../PACKAGENAME.orig > ~/rpmbuild/SOURCES/PKGNAME.REASON.patch
If you edit many files in one patch, you can also copy the original files using some consistent ending such as ".orig" before editing them. Then, you can use "gendiff" (in the rpm package) to create a patch with the differences. Do "man gendiff" for more information.
Try to ensure that in your patch the "context" matches exactly.
By default, patch will try to apply patches even when the match is imprecise with a "fuzz" value of 2,
but the [ new RPM for Fedora 10] will change the default fuzz to 0.
You can work around this by adding "%define _default_patch_fuzz 2", but it's better to not
have the problem.
You should send your patch upstream, and document in your spec file
the upstream bug/email that includes it.  See [[Packaging/PatchUpstreamStatus]].
==== %prep section: Unmodified files ====
Sometimes, you'll package just a straight file that doesn't need to be uncompressed, e.g., a "Source1:" that is just a simple PDF file.  These might not be from external sources, e.g., perhaps you've had to create a few additional files that weren't in the original sources so that the package cleanly installs in Fedora.  You can "prep" those into the build directory by doing this (replace "1" with whatever number it is):
  cp -p %SOURCE1 .
=== %build section ===
The "%build" section is sometimes complicated; here you configure and compile/build the files to be installed.
Many programs follow the GNU configure approach (or some variation).  By default, they will install to a prefix of "/usr/local" (/usr/local/bin, /usr/local/lib, etc.), which is a reasonable default for unpackaged files - but since you ''are'' packaging it, you will want to change the prefix to "/usr". Since the GNU "configure" system is so common, rpm pre-defines a macro named "%configure", which invokes GNU configure with the right options (e.g., it changes --prefix to /usr).  This means that some variation of this will often work as a build command:
  make %{?_smp_mflags}
Sometimes you'll want to override the variables of a makefile; you can easily do that by passing them as parameters to make, like this:
make %{?_smp_mflags} CFLAGS="%{optflags}" BINDIR=%{_bindir}
If you need to do something complicated with GNU-generated configure, take a look at [ "GNU autoconf, automake, and libtool"].  A good presentation on these as well as "make" is [ "Open Source Development Tools: An Introduction to Make, Configure, Automake, Autoconf" by Stefan Hundhammer].
If you include some self-tests (and that's a good idea), put them in a separate "%check" section that immediately follows the "%build" area, instead of including them in %build.  That way, it will be easy for the system to skip unnecessary self-tests.
=== %check section ===
The "%check" section does testing, often it's "make test".
This is not documented in many other sources of RPM info.
=== %install section ===
The "%install" section is a set of script commands to "install" the program. The commands in this section should copy the files from a directory inside the "build directory" %{_builddir} (normally ~/rpmbuild/BUILD/''something'') into the build root directory, %{buildroot} (normally /var/tmp/''something''), creating the directories inside %{buildroot} as necessary.
'''Watch out''': Some of the terminology is very misleading:
* The "build directory" (under which compilations occur during %build) and the "build root" (where files are copied into during the %install process) are '''different'''.  The point of the %install process is to copy files, such as those under the build directory, to the right place in the build root. Perhaps "buildroot" should be called "installroot", but it's too late now, the terminology is entrenched.
* The build directory is normally ~/rpmbuild/BUILD.  The %prep stage will normally create a subdirectory underneath the build directory as part of %setup.  During %build, the current directory will actually start at %{buildsubdir}, that newly-created  subdirectory under the build directory.  Typically %{buildsubdir} is something like ~/rpmbuild/BUILD/%{name}-%{version}.
* The "%install" script is ''not'' used when the binary rpm package is installed by the end-user!! The term "%install" is misleading, in fact, the script must ''not'' install the programs in the REAL final locations (e.g., in /usr/bin), but under the buildroot %{buildroot}.
As noted in the guidelines,  "when adding file copying commands in the spec file, consider using a command that preserves the files' timestamps, eg. cp -p or install -p".  So, if the makefile lets you override the install command (typically named INSTALL), you might want something like INSTALL="install -p" as a make parameter.
Normally, the install script would first erase the %{buildroot} directory, and then do some variation of "make install" (ideally using DESTDIR=%{buildroot}, if the program supports it). Here's an example of an %install section:
rm -rf %{buildroot}
make DESTDIR=%{buildroot} INSTALL="install -p" install
Many older RPM documents suggest using "%makeinstall", which ''might'' work if "make install" doesn't support DESTDIR.  However, as noted in the Fedora guidelines, "Fedora's RPM includes a %makeinstall macro but it must NOT be used when make install DESTDIR=%{buildroot} works. %makeinstall is a kludge that can work with Makefiles that don't make use of the DESTDIR variable..." - but sometimes it has subtle failures.  See the Fedora guidelines if you want the details.
''Ideally, every program would have a "make install" that supported DESTDIR''; anything else is much harder.
So, if there's no "make install", or "make install" doesn't support DESTDIR, you may have to do things by hand.  So if there is no "make install", it would do some sort of sequence that would create directories that weren't already created by the "BuildRequires" packages (typically using install -d), followed by copying of files from the current directory (inside the build directory) into the buildroot directory. Running "make -n install" may make it easy to determine what it should be. For example:
rm -rf %{buildroot}
cp -p mycommand %{buildroot}%{_bindir}/
A nice solution, of course, would be to patch the makefile so that there ''is'' a "make install" that supports DESTDIR.
=== %files section ===
The %files section identifies what files and directories were added by the package - and thus, which files and directories are ''owned'' by the package.  Ownership is important - when you type "rpm -qif ''blah''",  you'll see who owns ''blah''.
==== %files Basics ====
The %files section normally begins with a %defattr line which sets the default file permissions. The format of this is %defattr(<file permissions>, <user>, <group>, <directory permissions>), that is, one can specify the permissions to apply to files and directories in the %files section. The fourth parameter is often omitted. Usually one uses %defattr(-,root,root,-), where "-" means "use the default permissions".
This is followed by names or patterns of the directories or files to be installed and owned by this package. You should use macros for directory names, e.g., use %{_bindir}/myfile instead of /usr/bin/myfile, and %{_sbindir}/killaccount instead of /usr/sbin/killaccount.  If a name or pattern begins with "/" when expanded, then it is presumed to have been copied into the %{buildroot} followed by that pattern; when installed on the final system, it will be copied into that name ''without'' the buildroot prefix.  If you don't precede the pattern with "/", then it is presumed to be in the current directory (e.g., inside the build directory) - this is used for "documentation" files.  So if your package just installs /usr/bin/mycommand, then your %files section ''could'' simply say:
Any file or directory identified in the %files section is ''owned'' by the defining package. You should make sure that you declare ownership of every new file or directory the package creates.  You can use wildcards (*) which match a set of files - this makes the package less sensitive to changes. For example, you can declare that all the files that were copied into %{buildroot}/usr/bin are owned by this package by declaring:
Note that "%{_bindir}/*" does not claim that this package owns the /usr/bin directory - it claims that all the files that were installed inside the ''build root'' 's /usr/bin are owned by the package.
If you list a ''directory'' in the %files section, then you are claiming that this package owns that subdirectory and all files and directories in it, recursively (''all'' the way down) if they are present in the build root.  Do not list the "/usr/bin" or "%{_bindir}" directories directly in your %files list, because that would claim ownership of /usr/bin and everything inside it.  Claiming ownership of "%{_bindir}/*" is fine, though; that just claims ownership of the subdirectories and files you placed ''under'' %{buildroot}/%{_bindir}.  If you create a subdirectory such as %{_datadir}/%{name}, (/usr/share/NAME), you ''should'' include that directory in the %files list:
It's usually easier to use wildcards for filenames, and that's also better at copying with changes in upstream.  Older RPM documentation typically shows long lists under %files with individual names, such as /usr/bin/program1 followed by /usr/bin/program2.  Because of the way Fedora now uses buildroots, that is no longer necessary.
It's an error if ''no'' file matches the wildcard of a line, so only note the directories that actually matter.  Also, you can't identify the same file or directory more than once.  Finally, it's an error to have something in the buildroot and ''not'' listed under %files; the whole point of copying something into the buildroot is because you intend to have it installed in the final system.  If you don't intend that, remove those files during the %install process.
It is also possible to exclude files from a previous match by using a %exclude glob. This can be useful for including "almost all" of the files that match a different glob. However, note that, like any other file glob, even a %exclude glob will fail if it matches nothing. (This might be considered counterintuitive, as the whole point is essentially to ensure that a certain file ISN'T there, so this rule is especially important to remember.)
==== %files prefixes ====
You may need to add one or more prefixes to a %files entry (if more than one, use a space to separate them).
Typically there is a "%doc" entry with a list of documentation files that didn't get copied into the buildroot; usually there is at least a README and LICENSE file.  You ''must'' include the license file, if there is one. You may prefix some of these with %attr(mode, user, group) to set the file permission mode, user, or group.  You don't need to claim ownership of the /usr/share/doc/%{name} directory, that's automatic.  Any %doc entry must not affect the runtime of the application (if it is in %doc, the program must run properly if it is not present).
If you save configuration files (under /etc - don't put them under /usr), you should normally prefix them with %config(noreplace) unless this program version uses a non-backwards-compatible configuration format (in which case, prefix them with %config).
Prefixing a %files entry with "%attr(mode, user, group)" lets you set the permissions for particular file(s), e.g., "%attr(0644, root, root)".  A "-" means "use the default".
If a file is in particular natural language, use %lang to note that. E.G.:
%lang(de) %{_datadir}/locale/de/LC_MESSAGES/tcsh*
Some documentation claims that %license and %readme are valid prefixes; they are ''not'' valid in Fedora.  Use %doc instead.
==== %files and Filesystem Hierarchy Standard (FHS) ====
You should follow the [ Filesystem Hierarchy Standard (FHS)], i.e., ordinary application executables go into /usr/bin, global configuration files go into /etc, ordinary libraries go into /usr/lib, and so on, with one exception: executables that should ''not'' normally be executed directly by users or administrators should go into a subdirectory of /usr/libexec; usually you'd refer to the necessary directory as "%{_libexecdir}/%{name}".
You shouldn't be installing files under /usr/local; that is where ''unpackaged'' files go.
Typically there will be a "prefix" attribute that lets you set the prefix to be "/usr" instead of "/usr/local".
Unfortunately, many programs' "normal" installation routines do not follow the FHS.
In particular, many programs normally place architecture-independent libraries under /usr/lib, instead of
under /usr/share as the FHS requires.
The [ FHS /usr/lib section] says that
/usr/lib is for architecture-''dependent'' data (e.g., ELF files like .so files), while
[ /usr/share] is for
architecture-''independent'' data.  That way, systems with different CPUs can share /usr/share.
There are many exceptions to this rule in Fedora (e.g., Python and Perl), but Fedora applies this rule more
strictly than some distributions.  Note, for example, that rpmlint will complain if you
put just about anything other than ELF files into /usr/lib.
==== %files example ====
Here's a simple example of a %files section:
=== Scriptlets ===
You can add sections so that code will run when packages are installed or removed on the real system (as opposed to just running the %install script, which only does a pseudo-install to the build root).  These are called "scriptlets", and they are usually used to update the running system with information from the package.
The scriptlets in %pre and %post are run before and after a package is installed (respectively). The scriptlets %preun and %postun are run before and after a package is uninstalled. The scriptlets %pretrans and %posttrans are run at start and end of a transaction.  See [[Packaging/ScriptletSnippets]] for more examples and details.  For example, every binary RPM package which stores shared library files (not just symlinks) in any of the dynamic linker's default paths, must call ldconfig in %post and %postun (post-install and post-uninstall). If the package has multiple subpackages with libraries, each subpackage should also have a %post/%postun section that calls /sbin/ldconfig. For example:
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
''Beware'': The "-p" option specifies what ''command processor'' to use for the commands on the following lines.
If there are no following lines, then using /sbin/ldconfig as the "command processor" is a minor efficiency improvement compared to putting "/sbin/ldconfig" on the next line, and letting the shell invoke it.
That's because by using "-p",
the shell isn't invoked simply to invoke a single program.
But if you have multiple shell commands,
don't use "-p" or /sbin/ldconfig after it!  Instead, leave it blank, and include the shell commands under it.
If you are going to run programs in scriptlets, they must be installed before you run them.
You have to use special variants of the "Requires:" tag, so that
the program will be installed before you try to use it.  These are of the form "Requires(CONTEXT):", e.g., "Requires(post)".
Most scriptlets (%pre, %post, %preun, and %postun) provide an argument you can use,
accessed via $1, which is the number of packages of this name which will be left on the system
when the action completes.
Don't compare for ''equality'' with 2; check if they are ''greater than or equal than'' 2, since
users can arrange to have multiple versions of a package installed simultaneously.
For %pretrans and %posttrans, $1 is always 0.
For example, after adding an info manual to the system the dir file
which indexes the info manuals should be updated.
Basically, after you install the info manual, you need to run the program install-info.  That's fine, except that install-info is part of package info, and there's no guarantee that info is installed unless we require it. Also, if "install-info" fails, we don't want to fail ''all'' processing. Here's one way to do that:
Requires(post): info
Requires(preun): info
/sbin/install-info %{_infodir}/%{name}.info %{_infodir}/dir || :
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
Another scriptlet-like abilility are ''triggers''.  You can define triggers for when ''other'' packages
are installed or uninstalled.  See ''Maximum RPM'' for more information about triggers.
=== Macros ===
Spec files may contain "macro" references (text beginning with "%"), which are replaced with other values.
You can follow % by a word, e.g., "%name", but just like shell variables you must bracket the name with {...}
if letters or digits immediately follow, e.g., "%{name}".
As noted in the
[[Packaging/Guidelines| Packaging Guidelines]],
There are two styles for referring some values such as the rpm Build Root and Optimization Flags:
* "macro style": %{buildroot}, %{optflags}
* "variable style": $RPM_BUILD_ROOT, $RPM_OPT_FLAGS
Pick a style and use it consistently throughout your packaging; this document uses "macro style".
Here are some typical macros:
! Macro !! Typical Expansion
| %{_bindir} || /usr/bin
| %{_builddir} || ~/rpmbuild/BUILD (build directory; see %buildsubdir)
| %{buildroot} || /var/tmp/... - buildroot, where files are "installed" during %install
| %{buildsubdir} || %{_builddir}/%{name} - where files are compiled during %build. It's under %{_builddir}, set after %setup.
| %{_datadir} || /usr/share
| %{_defaultdocdir} || /usr/share/doc
| %{dist} || Distribution+version short name (e.g., ".fc9")
| %{fedora} || Number of fedora release (e.g., 9)
| %{_includedir} || /usr/include
| %{_infodir} || /usr/share/info
| %{_initrddir} || /etc/rc.d/init.d
| %{_libdir} || /usr/lib
| %{_libexecdir} || /usr/libexec
| %{_localstatedir} || /var
| %{_mandir} || /usr/share/man
| %{name} || Name of package, set by Name: tag
| %{_sbindir} || /usr/sbin
| %{_sharedstatedir} || /usr/com
| %{_sysconfdir} || /etc
| %{version} || Version of package, set by Version: tag
To see more about macros you
can look in /etc/rpm/* and the "macros" files under "/usr/lib/rpm/",
especially /usr/lib/rpm/macros.
You can also use "rpm --showrc" to show the values rpm will use for all of the options
currently set in rpmrc and macro configuration files.
You can set your own macro values using %define; be sure to define them before you use them. Macro definitions
can refer to other macros.  For example:
%define myvalue 50
You can use rpmbuild to find the value of some macro, using its "-E" (--eval) option. For example, to find the current expansion of %{_bindir} in myfile.spec, you can run:
rpmbuild -E '%{_bindir}' myfile.spec
[[Packaging/RPMMacros]] has more information on macros, as does
[ RPM Guide chapter 9].
=== Other tags ===
We noted the "Requires" and "BuildRequires" tags earlier.
There are a few other tags for controlling dependencies:
Provides, Obsoletes, Conflicts, and BuildConflicts.
* "Provides:" lets you list ''virtual'' package names that this package provides.  Sometimes there are several different packages that can provide a function, and using packages won't care which one.  In that case, each of the packages that provide the function should "provide" a virtual package, and then using packages can list the virtual package name under "Requires:".  For example, several different packages might provide "latex"; if you depend on the virtual package "tex(latex)", then users can choose which package to get "latex" from.  If you provide virtual packages, you might also want to use the [ "alternatives" system], but be careful: "alternatives" settings are ''system-wide'', so if multiple users on the same system might want different defaults, don't use the alternatives system. You can find out what a given package provides (both virtual and non-virtual names) by querying "rpm -q --provides PACKAGENAME".  Some virtual packages in Fedora are:
** ''MTA'' : Used for mail transport agents, such as sendmail.
** ''tex(latex)'' : Used for latex
* "Obsoletes:" lets you state that installing this package should (normally) cause the removal of the other named package(s).  This is useful when a package's name changes, or when a package wholly replaces a different package.
* "Conflicts:" lets you state what packages cannot be installed simultaneously this one.  Obviously, try to avoid this if you can; see [[Packaging/Conflicts]] if you think you need to use it.
* "BuildConflicts:" lets you state what packages cannot be installed when building this package. Obviously, try to avoid this if you can.
You can control which architectures a package builds (or doesn't build).  For example, if your package can't compile on ppc, you can do this:
ExcludeArch: ppc
There's also an "ExclusiveArch" tag. The valid architectures one can specify in these tags are listed in the [[Architectures]] section.
=== Subpackages ===
A spec file can define more than one binary package, e.g., client and server,
or runtime and developer packages.
If there's a large amount of documentation, it may be split into a NAME-doc subpackage.
You will always have one spec file and one source RPM (SRPM), even if there are
multiple binary RPMs that they generate.
A spec file that produces multiple binary packages still has only
one creation process, so there is only one
%prep, %build, %check, and %install section that creates all the files
for all the packages.
In a spec file, use the %package directive to start defining a subpackage:
%package sub_package_name
By default, the subpackage name is PACKAGE_NAME, "-", SUBPACKAGE_NAME; you can
use "-n" to override this and make a new name:
%package -n new_sub_package_name
After the %package directive, list the tags for the subpackage.
This should include at least the "Summary:" and "Group:" tags and directives
"%description SUBPACKAGE_NAME" and "%files SUBPACKAGE_NAME".
Anything not specified by the subpackage will be inherited from its parent.
For the directives, if you used "-n" with %package,
you'll need it again for these directives.
You need to specify the name for the other directives, e.g., %pre and %post,
if you use them in the subpackage.
[ See the RPM Guide section on subpackages] for more information.
=== Conditionals ===
You can insert conditional statements.
E.G., you can test if you are creating a binary for a certain architecture
the negated version with:
or the more general conditional:
There is an optional "%else" section; all of these are closed with "%endif".
=== Miscellaneous hints ===
If you want to see lots of examples of scriptlets, you can show all the scriptlets on installed programs using:
  rpm -qa --queryformat "\n\nPACKAGE: %{name}\n" --scripts | less
[[Packaging/FrequentlyMadeMistakes]] has information on frequently-made mistakes.
Don't try to interact with the user; RPM is designed to support batch installs.  If an application needs to show a EULA, that needs to be part of its initial execution, not its installation.
You might not want to start services, because in a big install that could slow things down. If you install an init script, consider using chkconfig to arrange for the service to be started and stopped on the next reboot.  Before ''uninstalling'' you should normally try to stop its services if it's running.
Uninstall should reverse most changes made during installation, but don't remove any user-created files.
Normally, if there are binary executables, a separate "debug" package is created with the symbols, and the symbols are stripped from the normal binary packages.  If this shouldn't happen, you can disable the package-creation and stripping with:
%define _enable_debug_package 0
%define debug_package %{nil}
%define __os_install_post /usr/lib/rpm/brp-compress %{nil}
A way to check for the version of Fedora in a spec file for conditional builds is:
%if 0%{?fedora} <= <version>
(The ? causes the macro to evaluate to blank if %fedora is not defined, and this causes the end result to be "0", which is a number and thus ok, while not interfering with the result if there is actually a value for %fedora.)
Note that the previous trick DOES NOT work in Koji "scratch" builds - %fedora is set during the creation of a source RPM. (Thus, this trick does work in actual Koji builds as the system extracts sources from the source RPM and rebuilds the source RPM with the appropriate %fedora value.)
There are also some recommendations and controversial tricks on
[[PackageMaintainers/Packaging Tricks]].
GUI programs ''must'' have a desktop entry (so that people can invoke it from a graphical menu).
The [ desktop entry spec] (for .desktop files) and
[ icon theme spec] defines
how to do that (e.g., how to use /usr/share/icon).
Some older documents about RPM have the most information, but some older documents make claims that are no longer true:
* rpm files are no longer placed in a shared /usr/src/redhat directory.  This is an obsolete way of using rpm and ''not'' recommended; modern systems set a %{_topdir} instead like ~/rpmbuild.
* the %install process does not install files in their final location.  Instead, it "installs" files to the buildroot.
* The "rpm" command no longer creates packages (e.g., "rpm -ba" was once legal). Use the separate "rpmbuild" program instead.
== Quick test with rpmlint ==
Before trying to build anything from it, you might want to run ''rpmlint'' on the spec file:
rpmlint program.spec
This will catch many errors early. If the reported error doesn't make sense,
run it again with the "-i" option (this gives longer messages).
Generally, you should not have errors from rpmlint, but sometimes
rpmlint is excessively noisy.
[ Fedora packaging guidelines]
explain which ones to ignore, e.g., ignore "no-packager-tag" and "no-signature" errors.
== Creating RPMs from the spec file ==
Once you've create a spec file, say "program.spec", you can create
source and binary RPMs by simply running this:
  $ rpmbuild -ba program.spec
This will attempt to perform the following stages:
* %prep (preparation) stage, which uncompresses and installs the sources and patches into %_builddir (a subdirectory of ~/rpmbuild/BUILD)
* %build stage, which builds (e.g., compiles) the files to be installed in %_builddir. Usually this is some equivalent of "make".
* %install stage, which copies the files from the build directory %_builddir (which would be under ~/rpmbuild/BUILD) into the buildroot directory, %{buildroot}.  The buildroot directory is set by the earlier "BuildRoot:"; if you leave it to its normal value beginning %{_tmppath}/%{name}..., then the buildroot will be inside /var/tmp.
* Create the binary and source RPM packages (.rpm and .src.rpm files).  The binary RPM files are created using the information from the %files list.
Watch out: the "build directory" (where compilations occur during %build) and the "build root" (where files are installed during the %install) are ''different''.
When things go wrong, you can "cd" into the appropriate directory and see what's left over.
If you want to skip earlier stages, use the "--short-circuit" option; this is handy if you had a successful build, but have an error in the %install section.  For example, to restart at the %install stage (skipping earlier stages), do this:
  $ rpmbuild -bi --short-circuit program.spec
If it is successful, you'll find your binary RPM(s) in the "~/rpmbuild/RPMS/"
subdirectory, and the source RPM in "~/rpmbuild/SRPMS".
If you just want to create a source RPM (.src.rpm), do this in the SPECS directory:
rpmbuild -bs program.spec
This will create the source RPM in ~/rpmbuild/SRPMS.  Creating ''only'' a source rpm (.src.rpm) is quite quick, because rpm simply needs to copy the .spec file and associated SOURCES files into a .src.rpm file.  Creating a binary rpm typically takes ''much'' longer, because this requires running the %prep, %build, and %install scripts.
== Testing RPMs you've built ==
If you "cd" to the "~/rpmbuild/RPMS" directory, and then cd to the architecture subdirectory,
you'll find some binary rpms. You can quickly see their files and their permissions by using rpmls
(check to see that they are what you expect):
$ rpmls *.rpm
Run rpmlint on the ''binary'' RPM (rpmlint works on .spec files, binary RPMs, and source RPMs, finding different things in each):
$ rpmlint *.rpm
If those look okay, you can become root and try to install them:
# rpm -ivp XYZ1.rpm XYZ2.rpm XYZ3.rpm ...
Then, you can test them out.  If it's a command-line tool, can you invoke it
without prepending /usr/bin?  If it's a GUI tool, does it show up in the menu
(if it doesn't, something is wrong with your .desktop entry).
You can uninstall them later using:
# rpm -e XYZ1 XYZ2 XYZ3
If that all works, you can use Mock to do a rigorous test that you have
accurate build requirements.  See [[PackageMaintainers/MockTricks]]
for more information about how to use Mock; once your account is a member of the "mock" group,
you can run commands like this to do local testing:
$ mock -r fedora-9-i386 rebuild path_to_source_RPM
Once Mock works on your system, you can use Koji (which uses Mock) to do builds on
many different systems, some of which you may not have.
[[PackageMaintainers/Join]] and [[PackageMaintainers/UsingKoji]] have more information about Koji.
Once it's set up, you can test your source RPM
on a variety of platforms by running commands like:
$ koji build --scratch dist-f9 path_to_source_RPM
You can replace dist-f9 with dist-f8, dist-f10, etc., to try other releases. Don't use "dist-rawhide", that's not really rawhide.  Remember, the values of %fedora, %fc9, etc., will not be correct for a scratch build, so this won't work if your spec file does something different based on those values.
Your koji builds can only depend on packages that are actually in the TARGET distribution repository.  Thus, you can't use koji to build for released distributions if your package depends on other new packages that Bodhi hasn't released yet.  You ''can'' use koji to build for rawhide (the next unreleased version), even if it depends on other new packages, as long as the other packages were built in the CVS "devel" section as described below.
If you need to build against a package that is not yet a stable released update, you can file a ticket with rel-eng at: and request that that package be added as a buildroot override.
== Helpful tools ==
The "rpmdevtools" package has a number of helpful tools; "rpm -qil rpmdevtools" will show you what it installs.
One particularly useful tool is rpmdev-bumpspec, which has this form:
rpmdev-bumpspec --comment=COMMENT --userstring=NAME+EMAIL_STRING SPECFILES
rpmdev-bumpspec will bump the release tag in the spec file(s), and add a changelog comment with the right datetime and version format.  COMMENT should typically start with "- ".
You might find [ RUST] useful (GPL).
It is "a drag &amp; drop RPM creation GUI and a 'sandboxing' toolkit that allows you to do software installations within a chrooted environment and automatically generate RPMs from arbitrary source code, without ever seeing a spec file."
If you're creating spec files, it can help you determine the %files.
(Note: it is no longer at "".)
[ Alien] converts between package formats.
It won't produce clean source RPMs, but converting an existing package
might provide helpful information.
== Guidelines and rules ==
When you create your packages, you'll need to follow the following rules and guidelines:
* [[PackageMaintainers/Join| How to join the Fedora Package Collection Maintainers]] - describes the process for becoming a Fedora package maintainer
* [[Packaging/Guidelines|Packaging Guidelines]]
* [[Packaging/NamingGuidelines| Package Naming Guidelines]]
* [[Packaging/DistTag| Dist Tag Guidelines]]
* [[Packaging/ReviewGuidelines| Package Review Guidelines]]
There are many official guidelines that will help you with specific circumstances
(Java programs, OCaml programs, GNOME programs, etc.); the
[[Packaging/Guidelines|Packaging Guidelines]] include cross-references to those guidelines.
You can also learn more from the [[SIGs]] and
[[PackageMaintainers|Package Maintainers]] sections.
[ You can also see the list of all Wiki pages about Packaging] to see if any apply.
Failing that, you might find some useful recommendations in the unofficial
[ Packaging Drafts] and [ Packaging Drafts To Do].
These are unofficial, obviously.
You might find ideas from [ SuSE],
[ Debian], but
[ distributions differ in their rules], so do not presume they can be used directly.
The .spec files that you create must be open source software, as noted in the
[ CLA].
== For more information ==
The [[PackageMaintainers|Package Maintainers]] page links to many other useful pages, and the
[[PackageMaintainers/UpdatingPackageHowTo|Updating Package HOWTO]] describes how to update
an existing package you already maintain in Fedora.
For more information, outside of the Fedora Wiki, see:
* [ How to build RPM packages on Fedora] - very brief run-through
* Packaging software with RPM (developerWorks) [ Part 1], [ Part 2], and [ Part 3]
* [ Fedora Packager's Handbook]
* [ When Sally met Eddie] - a simple tale, but little detail
* [ Maximum RPM Book] - most complete information, but in some cases old/obsolete
* [ RPM Guide, section on creating RPMs] - this has lots of good information, and is slightly more up-to-date, but is a draft
* [ Developer's guide, section on building RPMs]
* [ Creating RPMS slides] from Guru Labs
* [ The fight, my first attempt to make a readable rpm package building introduction.]
* [ RPM Tutorial (Fullhart)]
* [ RPM HOWTO: RPM at Idle by Donnie Barnes]
* [ RPM HowTo] by Dawson
* [ SuSE build tutorial] - but about SuSE, not Fedora. [ Cross-distribution package HOWTO] has hints if you're building one RPM for many distributions.
* [ Mandriva Rpm HowTo (en)] ([ alt]) is an RPM tutorial, though for Mandriva (nee Mandrake).  Note: In Fedora, do ''not'' recompress original tarballs, as Mandriva suggests, because that would change their cryptographic hashes.
* [ Creating Your Own Linux RPM's - The Initial Software Build] is another brief intro, but it makes the point that "The process of building RPM's is much simpler than creating packages for Solaris... Fewer steps, and the ability to add all of your software information into one specification file, makes for a much tighter (and easier to modify or reproduce) software packaging system."
* [ All you need to know about RPM] (more about installing packages than creating them)
* The [ Wiki] has some useful information, such as the [ list of known RPM problems]
Note: The [] site has some documentation, but do not depend on it; that is the home of a ''fork'' of RPM maintained by Jeff Johnson.  The RPM used by Fedora (and Novell/SuSE) is instead based at [].
[ has a brief article] about this.

Latest revision as of 20:57, 26 May 2021