Packaging/Guidelines
From openSUSE
|
Packaging Guidelines
It is the reviewer's responsibility to point out specific problems with a package and a packager's responsibility to deal with those issues. The reviewer and packager work together to determine the severity of the issues (whether they block a package or can be worked on after the package is in the repository.) The Packaging Guidelines are a collection of common issues and the severity that should be placed on them. While these guidelines should not be ignored, they should also not be blindly followed. If you think that your package should be exempt from part of the Guidelines, please bring the issue to the opensuse-packaging mailing list.
Please remember that any package that you submit must also conform to the Review Guidelines .
Naming
You should go through the Packaging/Naming_Guidelines to ensure that your package is named appropriately.
Version and Release
Documentation covering the proper way to use the Version and Release fields can be found here: Packaging/Naming_Guidelines#Package_Version
Legal
There are various legal concerns to consider when packaging for openSUSE.
Licensing
You should review Packaging/Licensing_Guidelines to ensure that your package is licensed appropriately.
No inclusion of pre-built binaries or libraries
All binaries or libraries included with openSUSE packages must have been built from source code included in the source package. This is a requirement for the following reasons:
- Security: Pre-packaged binaries and libraries not built from source could include anything, malicious, dangerous, or just broken. Also, these are functionally impossible to patch.
- Compiler Flags: Pre-packaged binaries and libraries not built from source probably don't have the standard openSUSE compiler flags for security and optimization.
If you are in doubt as to whether something is considered a binary or library, here is some helpful criteria:
- Is it executable? If so, it is probably a binary.
- Does it contain a .so, ,so.#, or .so.#.#.# extension? If so, it is probably a library.
- If in doubt, ask your reviewer. If the reviewer is not sure, they should ask the Fedora Packaging Committee.
Packages which require non-open source components to build are also not permitted (e.g. proprietary compiler required).
Exceptions
- Some software (usually related to compilers or cross-compiler environments) cannot be build without the use of a previous toolchain or development environment (open source). If you have a package which meets this criteria, contact the Fedora Packaging Committee for approval.
- An exception is made for binary firmware, as long as it meets the requirements documented here: BinaryFirmware
Spec Legibility
All Fedora Package Spec Files must be legible. If the reviewer is unable to read the spec file, it will be impossible to perform a review. Fedora Spec files are not the place for entries into the Obfuscated Code Contest.
Writing a package from scratch
When writing a package from scratch, you should base your spec file on the Fedora spec file template (see Rpmdevtools ). Please put your preferences about spec file formatting and organization aside, and try to conform to this template as much as possible. This is not because we believe this is the only right way to write a spec file, but because it often makes it easier for QA to spot mistakes and quickly understand what you are trying to do.
Modifying an existing package
If you base a package on an existing non-Fedora package, be careful to verify its correctness and to understand exactly what goes on. Do not submit a package without knowing what those strange, but innocent-looking commands do.
In particular, you should
- verify any sources and patches.
- verify that the license stated in the spec file matches the actual license of the software (see Tags ),
- skim the summary and description for typos and oddities (see Summary and description ),
- make sure that the correct build root is used,
- ensure that macro usage is consistent (see Macros ).
Keep old changelog entries to credit the original authors. Entries that are several years old or refer to ancient versions of the software may be erased. If you end up doing radical changes and re-write most of the spec file anyway, feel free to start the changelog from scratch. In other words, use your best judgement.
Architecture Support
All Fedora packages must successfully compile and build into binary rpms on at least one supported primary architecture. Fedora packagers should make every effort to support all primary architectures.
Content, code which does not need to compile or build, and architecture independent code (noarch) are notable exceptions.
Architecture Build Failures
If a Fedora package does not successfully compile, build or work on an architecture, then those architectures should be listed in the spec in ExcludeArch. Each architecture listed in ExcludeArch needs to have a bug filed in bugzilla, describing the reason that the package does not compile/build/work on that architecture. The bug number should then be placed in a comment, next to the corresponding ExcludeArch line. New packages will not have bugzilla entries during the review process, so they should put this description in the comment until the package is approved, then file the bugzilla entry, and replace the long explanation with the bug number. The bug should be marked as blocking one (or more) of the following bugs to simplify tracking such issues:
Filesystem Layout
Fedora follows the Filesystem Hierarchy Standard with regards to filesystem layout. The FHS defines where files should be placed on the system. Fedora packages must follow the FHS. Any deviation from the FHS should be rationalized when the package is reviewed.
There are notable exceptions to this guideline for libexecdir (as specified in the [Coding Standards]) and /usr/target for cross-compilers.
Libexecdir
The Filesystem Hierarchy Standard does not include any provision for libexecdir, but Fedora packages can store appropriate files there. Libexecdir (aka, /usr/libexec on Fedora systems) should be used as the directory for executable programs that are designed primarily to be run by other programs rather than by users.
Fedora's rpm includes a macro for libexecdir, %{_libexecdir}. Packagers are highly encouraged to store libexecdir files in a package-specific subdirectory of %{_libexecdir}, such as %{_libexecdir}/%{name}.
Use rpmlint
Run rpmlint on the rpms to examine them for common errors, and fix them (unless rpmlint is wrong, which can happen, too). If you find rpmlint's output cryptic, the -i switch to it can be used to get more verbose descriptions of most errors and warnings. The rpmlint package is available in the Fedora repositories.
Rpmlint Errors
Rpmlint has the ability to make a lot of noise when it is run, even on perfectly valid packages. This section exists to help you decipher the messages, so that you can make fixes as necessary.
-
E: foo-package no-packager-tag: This error occurs because noPackager:value is defined in the spec file. In Fedora, we do not use thePackagertag, so you can ignore this error. -
E: foo-package no-signature: This error occurs because your package is not signed. Since Fedora doesn't store SRPMS in CVS (only the files inside them), you do not need to sign your package, and you can ignore this error. -
W: foo-package summary-ended-with-dot Summary of my package.: This error occurs because the entry in your spec forSummary:ended with a period. Just get rid of the period at the end of the line. -
E: foo-package wrong-script-end-of-line-encoding /path/to/somefile: This error occurs because of DOS line breaks in a file. Fix it with sed in the %prep section:%{__sed} -i 's/\r//' src/somefile-- DONT use dos2unix, that can cause build fail on FC3. -
E: foo-package invalid-lc-messages-dir /usr/share/locale/xx_XX/LC_MESSAGES/foo.mo: This error is a common false positive and usually should be ignored.
Changelogs
Every time you make changes, that is, whenever you increment the E-V-R of a package, add a changelog entry. This is important not only to have an idea about the history of a package, but also to enable users, fellow packages, and QA people to easily spot the changes that you make.
If a particular change is related to a Bugzilla bug, include the bug ID in the changelog entry for easy reference, e.g.
* Wed Jun 14 2003 Joe Packager <joe at gmail.com> - 1.0-2 - Added README file (#42).
You must use one of the following formats:
* Fri Jun 23 2006 Jesse Keating <jkeating@redhat.com> - 0.6-4 - And fix the link syntax.
* Fri Jun 23 2006 Jesse Keating <jkeating@redhat.com> 0.6-4 - And fix the link syntax.
* Fri Jun 23 2006 Jesse Keating <jkeating@redhat.com> - 0.6-4 - And fix the link syntax.
Tags
- The Packager tag should not be used in spec files. The identities of the packagers are evident from the changelog entries. By not using the Packager tag, you also avoid seeing bad binaries rebuilt by someone else with your name in the header. See also the Maximum RPM definition of the Packager tag at www.rpm.org . If you need to include information about the packager in the rpms you built, use
%packagerin your~/.rpmmacrosinstead. - The Vendor tag should not be used. It is set automatically by the build system.
- The Copyright tag is deprecated. Use the License tag instead, as detailed in Packaging/Licensing_Guidelines . Contact the upstream author if there is any doubt about what license the software is distributed under.
- The Summary tag value should not end in a period. If this bothers you from a grammatical point of view, sit down, take a deep breath, and get over it.
- Usually, the Pre
Req tag should be replaced by plain Requires. For more info, see Maximum RPM snapshot's fine grained dependencies chapter. - The Source tag documents where to find the upstream sources for the rpm. In most cases this should be a complete URL to the upstream tarball. For special cases, please see the Packaging/Source_URL Guidelines
BuildRoot tag
The BuildRoot value MUST be below %{_tmppath}/ and MUST contain at least %{name}, %{version} and %{release}. It may invoke mktemp since this is guaranteed to exist on every system. From there, packagers are expected to use a sane BuildRoot.
The recommended values for the BuildRoot tag are (in descending order of preference) :
%(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
%{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%{_tmppath}/%{name}-%{version}-%{release}-root
At one point, the second was a mandatory value, but it is now left to the packager to decide. If unsure, simply pick the first.
Prepping BuildRoot For %install
Packages in openSUSE CAN NOT have rm -rf %{buildroot} or rm -rf $RPM_BUILD_ROOT at the beginning of an %install section.
%clean
Each package must have a %clean section, which contains rm -rf %{buildroot} (or $RPM_BUILD_ROOT).
In the past, some packages checked that %{buildroot} was not / before deleting it. This is not necessary in openSUSE anymore.
Requires
RPM has very good capabilities of automatically finding dependencies for libraries and eg. Perl modules. In short, don't reinvent the wheel, but just let rpm do its job. There is usually no need to explicitly list eg. Requires: libqt4 when the dependency has already been picked up by rpm in the form of depending on libraries in the libqt4 package.
Build requirements are different. There's no automatic dependency find procedure for them, which means that you must explicitly list stuff that the package requires to build successfully. Typically, some -devel packages are listed there. Refer to the BuildRequires section.
Sometimes we know that a package requires eg. gtk2-devel 2.0 or newer to build (and thus gtk+ 2.0 or newer to run, but that's handled automatically). There are two things to consider here:
First, if the lowest possible requirement is so old that nobody has a version older than that installed on any target distribution release, there's no need to include the version in the dependency at all. In that case we know the available software is new enough. For example, the version in gtk2-devel 2.0 dependency above is unnecessary for all openSUSE distributions since (at least) release 10.2. As a rule of thumb, if the version is not required, don't add it just for fun.
Typically, the requirements for -devel packages need yet another look. They're not usually picked up automatically by rpm. If the foo-devel package has a foo-config script, you can try doing a foo-config --libs and foo-config --cflags to get strong hints what packages should be marked as foo's requirements. The newer approach would be to try pkg-config foo instead of foo-config. Examples:
$ gtk-config --cflags -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include $ gtk-config --libs -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib -ldl -lXi -lXext -lX11 -lm $ pkg-config gtk+-2.0 --cflags -I/usr/include/gtk-2.0 -I/usr/lib64/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng12 $ pkg-config gtk+-2.0 --libs -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lz -lfontconfig -lgobject-2.0 -lgmodule-2.0 -lglib-2.0
This means that gtk-devel should contain
Requires: glib-devel xorg-x11-devel
and gtk2-devel should contain
Requires: atk-devel cairo-devel glibc-devel glib2-devel pango-devel xorg-x11-devel
PreReq
Packages should not use the PreReq tag. Once upon a time, in dependency loops PreReq used to "win" over the conventional Requires when RPM determined the installation order in a transaction. This is no longer the case.
File Dependencies
Rpm gives you the ability to depend on files instead of packages. Whenever possible you should avoid file dependencies outside of /etc, /bin, /sbin, /usr/bin, or /usr/sbin. Using file dependencies outside of those directories requires yum (and other depsolvers using the repomd format) to download and parse a large xml file looking for the dependency. Helping the depsolvers avoid this processing by depending on the package instead of the file saves our end users a lot of time. There are times when other technical considerations outweigh these considerations. One specific example is packages installing into %{_libdir}/mozilla/plugins. In this case, mandating a specific browser in your package just to own this directory could drag in a large amount of needless packages. Requiring the directory to resolve the dependency is the better choice.
BuildRequires
In package development and testing, please verify that your package is not missing any necessary build dependencies. Having proper build requirements saves the time of all developers and testers as well as autobuild systems because they will not need to search for missing build requirements manually. It is also a safety feature that prevents builds with that would not otherwise fail, but would be missing crucial features. For example, a graphical application may exclude PNG support after its configure script detects that libpng is not installed.
Before adding BuildRequires to any package, please be comfortable with Requires .
There are two suggested ways of detecting missing BuildRequires. rpmdev-rmdevelrpms and mock. The first one is designed to remove all developer-related packages from your system. If the build fails or is missing certain features due to missing build dependencies, then the missing dependency needs to be found and added. Check the rpmdev-rmdevelrpms section to find out more.
mock is another good way to check build dependencies. Rather than remove all developer packages, it tries to build your package in a chroot. It makes no changes to your normal, daily environment and ensures that your package will build fine. However, mock may need a good internet connection to download all required packages. MockTricks page contains more information. Another mock-like tool, mach is also available in the Fedora repository.
rpmdev-rmdevelrpms
rpmdev-rmdevelrpms script within the rpmdevtools toolkit is a script written by Ville Skyttä that helps RPM packagers in finding missing BuildRequires. Simply run it and allow it to remove all *-devel packages and build tools like this example.
[root@build-fc1 /] # rpmdev-rmdevelrpms Found 52 devel packages: guile-devel-1.6.4-8.2 bison-1.875-5 m4-1.4.1-14 flex-2.5.4a-30 openssl-devel-0.9.7a-23 automake-1.7.8-1 fontconfig-devel-2.2.1-6.1 XFree86-devel-4.3.0-42 tcl-devel-8.3.5-93 SDL_image-devel-1.2.3-3 SDL_ttf-devel-2.0.6-0.fdr.3.1 pth-devel-2.0.0-0.fdr.1.1 libIDL-devel-0.8.2-1 atk-devel-1.4.0-1 gtk2-devel-2.2.4-5.1 libmng-devel-1.0.4-4 glib-devel-1.2.10-11 gtk+-devel-1.2.10-28.1 audiofile-devel-0.2.3-7 compface-1.4-0.fdr.3.1 esound-devel-0.2.31-1 libungif-devel-4.1.0-16 gnome-libs-devel-1.4.1.2.90-35 openldap-devel-2.1.22-8 aspell-devel-0.50.3-16 gpgme03-devel-0.3.16-0.fdr.2.1 freeglut-devel-1.3-1.20020125.3 e2fsprogs-devel-1.34-1 db4-devel-4.1.25-14 krb5-devel-1.3.1-6 autoconf-2.57-3 libtool-1.5-8 gdbm-devel-1.8.0-21 freetype-devel-2.1.4-5 pkgconfig-0.14.0-6 ncurses-devel-5.3-9 tk-devel-8.3.5-93 SDL-devel-1.2.5-9 SDL_mixer-devel-1.2.4-9 zlib-devel-1.2.0.7-2 libgpg-error-devel-0.6-0.fr.3.1 glib2-devel-2.2.3-1.1 pango-devel-1.2.5-1.1 libjpeg-devel-6b-29 libpng-devel-1.2.2-17 ORBit-devel-0.5.17-10.3 clamav-devel-0.65-0.fdr.4.1 cyrus-sasl-devel-2.1.15-6 libtiff-devel-3.5.7-14 imlib-devel-1.9.13-14 gdk-pixbuf-devel-0.22.0-3.0 pilot-link-devel-0.11.8-1 Remove them? [y/N] y[ ]Removing................................................................................................. ................................................................Done.
Then attempt to build your RPM package. Use yum to reinstall any packages that are already in BuildRequires. If your build fails after this point, then you need to read through the build process and ascertain the missing BuildRequires from the error messages within.
Be very careful to watch especially the configure part of the build process for missing optional libraries or tools that are desirable for the package.
By default, the script may attempt to remove some packages that your system needs to operate correctly. Usually, this will fail due to an unsatisfied dependency (and this, BTW is why the script is using rpm -e instead of yum remove...)
An example of this are the gettext and libgcj packages. gettext is usually a development-only package, but for example redhat-lsb depends on it. Also, it seems that RH9 Konqueror needs openssl-devel for SSL. If you wish to mark some packages so that they will be ignored by rpmdev-rmdevelrpms, do it in /etc/rpmdevtools/rmdevelrpms.conf or your personal /.rmdevelrpmsrc and pay special attention to the packages you treated this way when building.
Exceptions
There is no need to include the following packages or their dependencies as BuildRequires because they would occur too often. These packages are considered the minimum build environment. The derived list of all deps pulled in by this list is on Packaging/Full_ExceptionList .
bash bzip2 coreutils cpio diffutils fedora-release findutils gawk gcc gcc-c++ grep gzip info make patch redhat-rpm-config rpm-build sed shadow-utils tar unzip util-linux-ng which
Summary and description
The summary should be a short and concise description of the package. The description expands upon this. Do not include installation instructions in the description; it is not a manual. If the package requires some manual configuration or there are other important instructions to the user, refer the user to the documentation in the package. Add a README.SUSE, or similar, if you feel this is necessary. Also, please make sure that there are no lines in the description longer than 80 characters.
Please put personal preferences aside and use American English spelling in the summary and description. Packages can contain additional translated summary/description for supported Non-English languages, if available.
Trademarks in Summary or Description
Packagers should be careful how they use trademarks in Summary or Description. There are a few rules to follow:
- Never use "(TM)" or "(R)" (or the unicode equivalents, ™/®). It is incredibly complicated to use these properly, so it is actually safer for us to not use them at all.
- Use trademarks in a way that is not ambiguous. Avoid phrasing like "similar to" or "like". Some examples:
- BAD: It is similar to Adobe Photoshop.
- GOOD: It supports Adobe Photoshop PSD files, ...
- BAD: A Linux version of Microsoft Office
- GOOD: A word-processor with support for Microsoft Office DOC files
If you're not sure, ask yourself, is there any chance someone may get confused and think that this package is the trademarked item? When in doubt, try to leave the trademark out.
Encoding
Unless you need to use characters outside the ASCII repertoire , you will not need to be concerned about the encoding of the spec file. If you do need non-ASCII characters, save your spec files as UTF-8. If you're in doubt as to what characters are ASCII, please refer to this chart .
Non-ASCII Filenames
Similarly, filenames that contain non-ASCII characters must be encoded as UTF-8. Since there's no way to note which encoding the filename is in, using the same encoding for all filenames is the best way to ensure users can read the filenames properly. If upstream ships filenames that are not encoded in UTF-8 you can use a utility like convmv (from the convmv package) to convert the filename in your %install section.
Documentation
Any relevant documentation included in the source distribution should be included in the package. Irrelevant documentation include build instructions, the omnipresent INSTALL file containing generic build instructions, for example, and documentation for non-Linux systems, e.g. README.MSDOS. Pay also attention about which subpackage you include documentation in, for example API documentation belongs in the -devel subpackage, not the main one. Or if there's a lot of documentation, consider putting it into a subpackage. In this case, it is recommended to use *-doc as the subpackage name, and Documentation as the value of the Group tag.
Also, if a package includes something as %doc, it must not affect the runtime of the application. To summarize: If it is in %doc, the program must run properly if it is not present.
Compiler flags
Compilers used to build packages should honor the applicable compiler flags set in the system rpm configuration. This means in practice $RPM_OPT_FLAGS/%{optflags} for C, C++, and Fortran compilers. Honoring means that the contents of that variable is used as the basis of the flags actually used by the compiler during the package build. Adding to and overriding or filtering parts of these flags is permitted if there's a good reason to do so; the rationale for doing so should be reviewed and documented in the specfile especially in the override and filter cases.
Debuginfo packages
Packages should produce useful -debuginfo packages, or explicitly disable them when it is not possible to generate a useful one but rpmbuild would do it anyway. Whenever a -debuginfo package is explicitly disabled, an explanation why it was done is required in the specfile. Debuginfo packages are discussed in more detail in a separate document, Packaging/Debuginfo .
Devel Packages
If the software being packaged contains files intended solely for development, those files should be put in a -devel subpackage. The following are examples of file types which should be in -devel:
- Header files (e.g. .h files)
- Unversioned shared libraries (e.g. libfoo.so). Versioned shared libraries (e.g. libfoo.so.3, libfoo.so.3.0.0) should not be in -devel.
A good rule of thumb is if the file is used for development and not needed for the base package to run properly, it should go in -devel.
Pkgconfig Files
The placement of pkgconfig(.pc) files depends on their usecase. Since they are almost always used for development purposes, they should be placed in a -devel package.
A reasonable exception is when the main package itself is a development tool not installed in a user runtime, e.g. gcc or gdb. Packages containing pkgconfig(.pc) files must Recommend: pkg-config (for usability).
Requiring Base Package
Devel packages must require the base package using a versioned dependency: Requires: %{name} = %{version}.
Usually, subpackages other than -devel should also require the base package using a versioned dependency.
Shared Libraries
Whenever possible (and feasible), openSUSE Packages containing libraries should build them as shared libraries. In addition, every binary RPM package which contains shared library files (not just symlinks) in any of the dynamic linker's default paths, must call ldconfig in %post and %postun. If the package has multiple subpackages with libraries, each subpackage should also have a %post/%postun section that calls /sbin/ldconfig. An example of the correct syntax for this is:
%post -p /sbin/ldconfig %postun -p /sbin/ldconfig
Note that this specific syntax only works if /sbin/ldconfig is the only call in %post and %postun. If you have additional commands to run during the scriptlet, call /sbin/ldconfig at the beginning of the scriptlet, like this:
%post /sbin/ldconfig /usr/bin/foo --add %postun /usr/bin/foo --remove /sbin/ldconfig
Packaging Static Libraries
Packages including libraries should exclude static libs as far as possible (eg by configuring with --disable-static). Static libraries should only be included in exceptional circumstances. Applications linking against libraries should as far as possible link against shared libraries not static versions.
Libtool archives, foo.la files, should not be included. Packages using libtool will install these by default even if you configure with --disable-static, so they may need to be removed before packaging. Due to bugs in older versions of libtool or bugs in programs that use it, there are times when it is not always possible to remove *.la files without modifying the program. In most cases it is fairly easy to work with upstream to fix these issues. Note that if you are updating a library in a stable release (not devel) and the package already contains *.la files, removing the *.la files should be treated as an API/ABI change -- ie: Removing them changes the interface that the library gives to the rest of the world and should not be undertaken lightly.
Packaging Static Libraries
- In general, packagers are strongly encouraged not to ship static libs unless a compelling reason exists.
- We want to be able to track which packages are using static libraries (so we can find which packages need to be rebuilt if a security flaw in a static library is fixed, for instance). There are two scenarios in which static libraries are packaged:
- Static libraries and shared libraries. In this case, the static libraries must be placed in a *-devel-static subpackage, which
Requires*-devel subpackage. Separating the static libraries from the other development files in *-devel allow us to track this usage by checking which packagesBuildRequirethe *-devel-static package. The intent is that whenever possible, packages will move away from using these static libraries, to the shared libraries. - Static libraries only. When a package only provides static libraries you can place all the static library files in the *-devel subpackage. When doing this you also must have a virtual Provide for the *-devel-static package:
%package devel
Provides: foo-devel-static = %{version}
Packages which explicitly need to link against the static version must BuildRequire: foo-devel-static, so that the usage can be tracked.
- If (and only if) a package has shared libraries which require static libraries to be functional, the static libraries can be included in the *-devel subpackage. The devel subpackage must have a virtual Provide for the *-devel-static package, and packages dependent on it must
BuildRequirethe *-devel-static package.
Duplication of system libraries
For several reasons, a package should not include or build against a local copy of a library that exists on a system. The package should be patched to use the system libraries.
This prevents old bugs and security holes from living on after the core system libraries have been fixed.
Beware of Rpath
Sometimes, code will hardcode specific library paths when linking binaries (using the -rpath or -R flag). This is commonly referred to as an rpath, and in Fedora it is forbidden. Normally, the dynamic linker and loader (ld.so) resolve the executable's dependencies on shared libraries and load what is required. However, when -rpath or -R is used, the location information is then hardcoded into the binary and is examined by ld.so in the beginning of the execution. Since the Linux dynamic linker is usually smarter than a hardcoded path, we do not permit the use of rpath in Fedora.
There is a tool called check-rpaths which is included in the rpmdevtools package. It is a good idea to add it to the %__arch_install_post macro in your ~/.rpmmacros config file:
%__arch_install_post \ /usr/lib/rpm/check-rpaths \ /usr/lib/rpm/check-buildroot
When check-rpaths is run, you might see output like this:
ERROR 0001: file '/usr/bin/xapian-tcpsrv' contains a standard rpath '/usr/lib64' in [/usr/lib64]
Often, rpath is used because a binary is looking for libraries in a non-standard location (standard locations are /lib, /usr/lib, /lib64, /usr/lib64). If you are storing a library in a non-standard location (e.g. /usr/lib/foo/), you should include a custom config file in /etc/ld.so.conf.d/. For example, if I was putting 32 bit libraries of libfoo in /usr/lib/foo, I would want to make a file called "foo32.conf" in /etc/ld.so.conf.d/, which contained the following:
/usr/lib/foo
Make sure that you also make a 64bit version of this file (e.g. foo64.conf) as well (unless the package is disabled for 64bit architectures, of course).
Removing Rpath
There are several different ways to fix the rpath issue:
- If the application uses configure, try passing the --disable-rpath flag to configure.
- If the application uses a local copy of libtool, add the following lines to the spec after %configure:
%configure sed -i 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' libtool sed -i 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool
- Sometimes, the code/Makefiles can be patched to remove the -rpath or -R flag from being called. This is not always easy or sane to do, however.
- As a last resort, Fedora has a package called chrpath. When this package is installed, you can run
chrpath --deleteon the files which contain rpaths. So, in our earlier example, we'd run:
chrpath --delete $RPM_BUILD_ROOT%{_bindir}/xapian-tcpsrv
Make sure that you remember to add a BuildRequires: chrpath if you end up using this method.
Configuration files
Configuration files must be marked as such in packages.
As a rule of thumb, use %config(noreplace) instead of plain %config unless your best, educated guess is that doing so will break things. In other words, think hard before overwriting local changes in configuration files on package upgrades. An example case when /not/ to use noreplace is when a package's configuration file changes so that the new package revision wouldn't work with the config file from the previous package revision. Whenever plain %config is used, add a brief comment to the specfile explaining why.
Don't use %config or %config(noreplace) under /usr. /usr is deemed to not contain configuration files in openSUSE.
Initscripts
Currently, only SystemV-style initscripts are supported in Fedora. There are detailed guidelines for SysV-style initscripts here: Packaging/SysV_Init_Script
Desktop files
If a package contains a GUI application, then it needs to also include a properly installed .desktop file. For the purposes of these guidelines, a GUI application is defined as any application which draws an X window and runs from within that window. Installed .desktop files MUST follow the desktop-entry-spec , paying particular attention to validating correct usage of Name, GenericName, Categories , StartupNotify entries.
Icon tag in Desktop Files
The icon tag has to be short name without file extension:
-
Icon=comical
because it allows for icon theming (it assumes .png by default, then tries .svg and finally .xpm).
.desktop file creation
If the package doesn't already include and install its own .desktop file, you need to make your own, and include it as a Source: (e.g. Source3: %{name}.desktop). Here are the contents of a sample .desktop file (comical.desktop):
[Desktop Entry] Name=Comical GenericName=Comic Archive Reader Comment=Open .cbr & .cbz files Exec=comical Icon=comical Terminal=false Type=Application Categories=Graphics;
%suse_update_desktop_file usage
It is not simply enough to just include the .desktop file in the package, one MUST run %suse_update_desktop_file in %install (and have BuildRequires: update-desktop-files), to help ensure .desktop file safety and spec-compliance. %suse_update_desktop_file MUST be used if the package does not install the file or there are changes desired to the .desktop file (such as add/removing categories, etc). Here are some examples of usage:
- check desktop file
%suse_update_desktop_file %{name}
- install desktop file and change categories
%suse_update_desktop_file -i %{name} System Utility Core GTK FileManager
Macros
Use macros instead of hard-coded directory names (see Packaging/RPM_Macros ).
Having macros in a Source: or Patch: line is a matter of style. Some people enjoy the ready readability of a source line without macros. Others prefer the ease of updating for new versions when macros are used. In all cases, remember to be consistent in your spec file and verify that the URLs you list are valid. spectool (from the rpmdevtools package) can aid you in checking that whether the URL contains macros or not.
If you need to determine the actual string when it contains macros, you can use rpm. For example, to determine the actual Source: value, you can run:
rpm -q --specfile foo.spec --qf "$(grep -i ^Source foo.spec)\n"
Using %{buildroot} and %{optflags} vs $RPM_BUILD_ROOT and $RPM_OPT_FLAGS
There are two styles of defining the rpm Build Root and Optimization Flags in a spec file.
| macro style | variable style | |
|---|---|---|
| Build Root | %{buildroot} | $RPM_BUILD_ROOT |
| Opt. Flags | %{optflags} | $RPM_OPT_FLAGS |
There is very little value in choosing one style over the other, since they will resolve to the same values in all scenarios. You should pick a style and use it consistently throughout your packaging.
Mixing the two styles, while valid, is bad from a QA and usability point of view, and should not be done in openSUSE packages.
Handling Locale Files
openSUSE includes an rpm macro called %find_lang. This macro will locate all of the locale files that belong to your package (by name), and put this list in a file. You can then use that file to include all of the locales. %find_lang should be run in the %install section of your spec file, after all of the files have been installed into the buildroot. The correct syntax for %find_lang is usually:
%find_lang %{name}
In some cases, the application may use a different "name" for its locales. You may have to look at the locale files and see what they are named. If they are named myapp.mo, then you will need to pass myapp to %find_lang instead of %{name}.
After %find_lang is run, it will generate a file in the active directory (by default, the top level of the source dir). This file will be named based on what you passed as the option to the %find_lang macro. Usually, it will be named %{name}.lang. You should then use this file in the %files list to include the locales detected by %find_lang. To do this, you should include it with the -f parameter to %files.
%files -f %{name}.lang
%defattr(-,root,root,-)
%{_bindir}/foobar
...
If you are already using the -f parameter for the %files section where the locales should live, just append the contents of %{name}.lang to the end of the file that you are already using with -f. (Note that only one file may be used with %files -f.)
Here is an example of proper usage of %find_lang, in foo.spec:
...
%prep
%setup -q
%build
%configure --with-cheese
%install
make DESTDIR=$RPM_BUILD_ROOT install
%find_lang %{name}
%clean
rm -rf $RPM_BUILD_ROOT
%files -f %{name}.lang
%defattr(-,root,root,-)
%doc LICENSE README
%{_bindir}/foobar
%changelog
* Thu May 4 2006 Tom "spot" Callaway <tcallawa@redhat.com> 0.1-1
- sample spec that uses %%find_lang
Why do we need to use %find_lang?
Using %find_lang helps keep the spec file simple, and helps avoid several other packaging mistakes.
- Packages that use
%{_datadir}/*to grab all the locale files in one line also grab ownership of the locale directories, which is not permitted. - Most packages that have locales have lots of locales. Using
%find_langis much easier in the spec file than having to do:
%{_datadir}/locale/ar/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/be/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/cs/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/de/LC_MESSAGES/%{name}.mo
%{_datadir}/locale/es/LC_MESSAGES/%{name}.mo
...
- As new locale files appear in later package revisions,
%find_langwill automatically include them when it is run, preventing you from having to update the spec any more than is necessary.
Keep in mind that usage of %find_lang in packages containing locales is a MUST.
Timestamps
When adding file copying commands in the spec file, consider using a command that preserves the files' timestamps, eg. cp -p or install -p.
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.
Parallel make
Whenever possible, invocations of make should be done as
make %{?jobs:-j%jobs}
This generally speeds up builds and especially on SMP machines.
Do make sure, however, that the package builds cleanly this way as some make files do not support parallel building. Therefore you should consider adding
%jobs 3
to your ~/.rpmmacros file -- even on UP machines -- as this will expose most of these errors.
Scriptlets
Great care should be taken when using scriptlets in Fedora packages. If scriptlets are used, those scriptlets must be sane. Some common scriptlets are documented here: Packaging/Scriptlet_Snippets.
Scriptlets requirements
Do not use the Requires(pre,post) style notation for scriptlet dependencies, because of two bugs in RPM. Instead, they should be split like this:
Requires(pre): ... Requires(post): ...
For more information, see www.redhat.com .
Running scriptlets only in certain situations
When the rpm command executes the scriptlets in a package it indicates if the action preformed is an install, erase, upgrade or reinstall by passing an integer argument to the script in question according to the following:
| install | erase | upgrade | reinstall | |
|---|---|---|---|---|
| %pre | 1 | - | 2 | 2 |
| %post | 1 | - | 2 | 2 |
| %preun | - | 0 | 1 | - |
| %postun | - | 0 | 1 | - |
This means that for example a package that installs an init script with the chkconfig command should uninstall it only on erase and not upgrade with the following snippet:
%preun
if [ $1 -eq 0 ] ; then
/sbin/chkconfig --del %{name}
fi
See also /usr/share/doc/rpm-*/triggers, which gives a more formal, generalized definition about the integer value(s) passed to various scripts.
Scriplets are only allowed to write in certain directories
Build scripts of packages (%prep, %build, %install, %check and %clean) may only alter files (create, modify, delete) under %{buildroot}, %{_builddir} and valid temporary locations like /tmp, /var/tmp (or $TMPDIR or %{_tmppath} as set by the rpmbuild process) according to the following matrix
| /tmp, /var/tmp, $TMPDIR, %{_tmppath} | %{_builddir} | %{buildroot} | |
|---|---|---|---|
| %prep | yes | yes | no |
| %build | yes | yes | no |
| %install | yes | yes | yes |
| %check | yes | yes | no |
| %clean | yes | yes | yes |
Further clarification: That should hold true irrespective of the builder's uid.
Conditional dependencies
If the spec file contains conditional dependencies selected based on presence of optional --with(out) foo arguments to rpmbuild, build the source RPM to be submitted with the default options, ie. so that none of these arguments are present in the rpmbuild command line. The reason is that those requirements get "serialized" into the resulting source RPM, ie. the conditionals no longer apply.
Build packages with separate user accounts
When building software, which you have not conducted a full security-audit on, protect sensitive data, such as your GPG private key, in a separate user account.
The same applies to reviewers/testers. Rebuild src.rpms in a separate account which does not have access to any sensitive data.
Relocatable packages
The use of RPM's facility for generating relocatable packages is strongly discouraged. It is difficult to make work properly, impossible to use from the installer or from yum, and not generally necessary if other packaging guidelines are followed. However, in the unlikely event that you have a good reason to make a package relocatable, you MUST state this intent and reasoning in the request for package review.
Code Vs Content
It is important to make distinction between computer executable code and content. While code is permitted (assuming, of course, that it has an open source compatible license, is not legally questionable, etc.), only some kinds of content are permissable.
The rule is this:
If the content enhances the OS user experience, then the content is OK to be packaged in Fedora. This means, for example, that things like: fonts, themes, clipart, and wallpaper are OK.
Content still has to be reviewed for inclusion. It must have an open source compatible license, must not be legally questionable. In addition, there are several additional restrictions for content:
- Content must not be pornographic, or contain nudity, whether animated, simulated, or photographed. There are better places on the Internet to get porn.
- Content should not be offensive, discriminatory, or derogatory. If you're not sure if a piece of content is one of these things, it probably is.
- All content is subject to review by FESCo, who has the final say on whether or not it can be included.
Some examples of content which is permissable:
- Package documentation or help files
- Clipart for use in office suites
- Background images (non-offensive, discriminatory, with permission to freely redistribute)
- Fonts (under an open source license, with no ownership/legal concerns)
- Game levels are not considered content, since games without levels would be non functional.
- Sound or graphics included with the source tarball that the program or theme uses (or the documentation uses) are acceptable.
- Game music or audio content is permissible, as long as the content is freely distributable without restriction, and the format is not patent encumbered.
- Example files included with the source tarball are not considered content.
Some examples of content which are not permissable:
- Comic book art files
- Religious texts
- mp3 files (patent encumbered)
If you are unsure if something is considered approved content, ask on fedora-devel-list.
File and Directory Ownership
Your package should own all of the files that are installed as part of the %install process. Packages must not own files already owned by other packages. The rule of thumb here is that the first package to be installed should own the files that other packages may rely upon. This means, for example, that no package in Fedora should ever share ownership with any of the files owned by the filesystem or man package. If you feel that you have a good reason to own a file or that another package owns, then please present that at package review time.
Directory ownership is a little more complex than file ownership. Although the rule of thumb is the same: own all the directories you create but none of the directories of packages you depend on, there are several instances where it's desirable for multiple packages to own a directory. Examples of this are:
1) The package you depend on to provide a directory may choose to own a different directory in a later version and your package will run unmodified with that later version.
One common example of this is a Perl module. Assume perl-A-B depends on perl-A and installs files into /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A/B. The base Perl package guarantees that it will own /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi for as long as it remains compatible with version 5.8.8, but a future upgrade of the perl-A package may install into (and thus own) /usr/lib/perl5/vendor_perl/5.9.0/i386-linux-thread-multi/A. So the perl-A-B package needs to own /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A as well as /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/A/B in order to maintain proper ownership.
2) Multiple packages have files in a common directory but none of them requires others.
An example:
Foo-Animal-Emu puts files into /usr/share/Foo/Animal/Emu Foo-Animal-Llama puts files into /usr/share/Foo/Animal/Llama
Neither package depends on the other one. Neither package depends on any other package which owns the /usr/share/Foo/Animal/ directory. In this case, each package must own the /usr/share/Foo/Animal/ directory.
In all cases we are guarding against unowned directories being present on a system. Please see Packaging/Unowned_Directories for the details.
Duplicate Files
An openSUSE package must not contain any duplicate files in the %files listing.
File Permissions
Permissions on files must be set properly. Executables should be set with executable permissions, for example. Every %files section must include a %defattr(...) line. Here is a good default:
%files %defattr(-,root,root,-)
Unless you have a very good reason to deviate from that, you should use %defattr(-,root,root,-) for all %files sections in your package.
Users and Groups
Some packages require or benefit from dedicated runtime user and/or group accounts. Guidelines for handling these cases are in a separate Packaging/Users_And_Groups document.
Web Applications
Web applications packaged in openSUSE should put their content into /srv/www/%{name} and NOT into /var/www. This is done because:
-
/varis supposed to contain variable data files and logs./srv/wwwis much more appropriate for this. - Many users already have content in
/var/www, and we do not want any openSUSE package to step on top of that. -
/var/wwwis no longer specified by the Filesystem Hierarchy Standard
Conflicts
Whenever possible, openSUSE packages should avoid conflicting with each other. Unfortunately, this is not always possible. For full details on openSUSE Conflicts policy, see: Packaging/Conflicts .
Bundling of multiple projects
Packages in openSUSE should make every effort to avoid having multiple, separate, upstream projects bundled together in a single package.
Avoid bundling of fonts in other packages
Fonts in general-purpose formats such as Type1, OpenType TT (TTF) or OpenType CFF (OTF) are subject to specific packaging guidelines, and should never be packaged in a private application directory instead of the system-wide font repositories. For more information, see: Package layout for fonts.
All patches should have tags
All patches in openSUSE spec files SHOULD have a comment above them about their status. For details see Packaging/Patches page.
Application Specific Guidelines
Some applications have specific guidelines written for them, located on their own pages in the Packaging/ hierarchy.
Eclipse
Guidelines for Eclipse plugin packages: Packaging/Eclipse_Plugins
Emacs
Guidelines for Emacs/X-Emacs packages: Packaging/Emacs
Fonts
Guidelines for font packages: Packaging/Fonts_Policy
Haskell
Guidelines for Haskell packages: Packaging/Haskell
Java
Guidelines for java packages: Packaging/Java
Lisp
Guidelines for lisp packages: Packaging/Lisp
Mono
Guidelines for Mono packages: Packaging/Mono
OCaml
Guidelines for OCaml packages: Packaging/OCaml
OpenOffice.org
Guidelines for OpenOffice.org extension packages: Packaging/OpenOffice.org_Extensions
Perl
Guidelines for Perl packages: Packaging/Perl
PHP
Guidelines for PHP packages: Packaging/PHP
Python
Guidelines for Python addon modules: Packaging/Python
R
Guidelines for R module packages: Packaging/R
Ruby
Guidelines for Ruby packages: Packaging/Ruby
Tcl/Tk
Guidelines for Tcl/Tk extension packages: Packaging/Tcl

