Home Wiki > openSUSE:Specfile guidelines
Sign up | Login

openSUSE:Specfile guidelines

tagline: From openSUSE

RPM itself has very little limitations on what you can do in specfiles, so you could make them very complex. (Not that you should do so, out of consideration for other readers.) This guidelines tries to minimize the variations in specific areas so the specfiles are maintainable.

General Rules

All spec files must be legible. If other packagers are unable to read the spec file, it will be impossible to perform a review and to collaborate on the package.

Specfile Template

When writing a package from scratch, you should base your spec file on the spec file template (see rpmdevtools). A basic setup for a package MYPACK can be generated by

[1] osc-plugin-install devel:tools rpmdevtools


sudo zypper -p http://download.opensuse.org/repositories/devel:/tools/openSUSE_12.3/ -v in osc rpmdevtools (change URL according to your suse version)

osc mkpac MYPACK
wget http://upstream.example.org/source/.../MYPACK-1.0.tar.gz
rpmdev-newspec -t lib MYPACK
osc vc
vi MYPACK.spec


osc build
osc ci
osc in

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.

Spec files for specific languages can often be created with specialized tools like cpanspec or gem2rpm-opensuse. See also

Specfile 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 are in doubt as to what characters are ASCII, please refer to an ASCII chart.

Specfile Licensing

Due to legal reasons, spec files must have a license header. You can use the following template if you like:

# spec file for package python-$FOO
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
# upon. The license for this file, and modifications and additions to the
# file, is the same license as for the pristine package itself (unless the
# license for the pristine package is not an Open Source License, in which
# case the license is the MIT License). An "Open Source License" is a
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.

# Please submit bugfixes or comments via http://bugs.opensuse.org/


Use macros instead of hard-coded directory names (see Packaging Conventions 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. 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"

Caution: the above command works with %{name} and %{version}, but may fail with user defined macros.

Macros vs RPM variables

There are two styles of defining the 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.

RPM macros are expanded before the shell script that a section comprises, is run. Since sh is notoriously slow, it would seem that the %-style shall be preferred, also because one is already using other macros like %{_bindir} which have no variable equivalent.


Icon-obsolete.png This article or section refers to the version 'This section is copyed from Fedora which uses a Koji buildsystem that is totally different from our Open Build Service. Koji needs to upload specfile and SRPM online, while we don't. So it's useless to openSUSE.' and it is now obsolete!
Please refer to this article's discussion page for more information.

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, i.e. 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, i.e. the conditionals no longer apply.

Conditionals (New)

see openSUSE:RPM_conditional_builds


These are the rules for the preamble section of a specfile.

Naming / versioning

See Package naming guidelines.

Metadata Tags

  • The Packager tag must not be used in spec files. Rebuilding the RPM package elsewhere forces this packager value onto the third person, leading to subsequent confusion about who to contact. The identities of the packagers should be specified with changelog entries instead.
  • The Vendor tag must not be used for the same reason. In the Build Service, it is also automatically set; if you want to override it, use a prjconf-level %define.
  • The Copyright tag is deprecated. Use the License tag instead, as detailed in openSUSE:Packaging_guidelines#Licensing.
  • If the Source tag specifies a link to a dead URL, the build can fail even if the file is locally present. Thus prefer providing the download directory/page location in an extra comment instead.
  • The Group tag should only contain package groups following the openSUSE:Package group guidelines.
  • The BuildRoot tag should always be used, even if newer rpms override it anyway. The preferred path is %{_tmppath}/%{name}-%{version}-build.
  • The AutoReqProv tag defaults to on, so it is redundant to specify it when not actually wanting to turn it off.


  • It 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.
  • It should also be a short and concise description of the package. Lines should be wrapped at 80 columns.
  • The summary should fit all standard situations and not assume any special context.
  • It should be helpful alone, in alphabetically sorted or unsorted lists of some selected packages, and in alphabetically sorted or unsorted lists of all packages.
  • It should describe the package's main function and point out any special properties of the package to support the user comparing similar packages. For example, the two words "Web Browser" summarize any web browser, but using additional adjectives (like minimalistic, text-based or fast) helps characterize a specific package.


The description expands upon the summary. 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.

A limitation to 70 characters for the line length (due to limited size of description window in textmode YaST) is no longer necessary any longer. Like the Qt frontend, the yast2-ncurses package selector creates simple HTML from the plaintext description and displays that instead. (This is available since March 2012 in Factory.)

Please respect these HTML properties: Empty lines result in paragraphs. In a list environment, empty lines end the list. Linebreaks result in a single space, that means that a line break has no special effect. An unnumbered list environment starts with a line that starts with an asterisk or a minus sign followed by at least one whitespace. A line which continues a list item starts with at least two whitespaces

Also, the description should not exceed a reasonable size, more than 20 lines is probably too much.

The package description should help the user decide on the right package for the intended purpose without needing to test other similar packages first. This is the right place to inform the user more precisely about a package's functionality. It should contain further information about features and differences from other, comparable packages. If a package could harm a user's installation, the description should contain clear notes on its potential risks or side effects.

Please put personal preferences aside and use American English spelling in the summary and description. The RPM spec file contains only the English version of Summary and Description to keep the RPM database small. The localizations are managed by YaST.

The list of authors at the end of the description should not be included anymore [NB:since summer 2011]. If you plan on honoring the authors with a mention, use a separate AUTHORS file for the credits. If the file is not already part of the upstream package, you should create one, and use it like this:

Source2:        AUTHORS
cp %{S:2} .

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)" (nor 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 are 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.



RPM has very good capabilities of automatically finding dependencies for libraries and eg. Perl modules. In short, do not reinvent the wheel, but just let rpm do its job. There is usually no need to explicitly list e.g. Requires: libqt4 when the dependency has already been picked up by rpm in the form of depending on shared libraries in the libqt4 package.

If your package splits into sub-packages, they may need to require the base-package using a versioned dependency: Requires: %{name} = %{version}.

-devel sub-packages need to explicitly depend on packages with the shared libraries that the devel package has symlinks to, i.e. libfoobar-devel needs, for example, Requires: libfoo2 = %{version}, libbar5 = %{version}


PreReq is used for runtime requires during install. List here all requirements needed for pre and post install scripts.


Typical usage:

BuildArch: noarch

Use this with your package, if you have no architecture dependant files in your file list.

Note that all subpackages must be also noarch, if your main package is noarch.


Unlike with Requires, for BuildRequires there is no automatic procedure to find dependencies. You must explicitly list the packages that your package requires to build successfully. Having proper build requirements saves the time of all developers and testers because they will not need to search for missing build requirements manually. It is also ensures that the build is reproducible and uses always the same features. configure scripts, for example, may exclude PNG support depending on the availability of libpng in the build system. With BuildRequires: libpng-devel (or since openSUSE 11.4: BuildRequires: pkgconfig(libpng14), you ensure that the build will fail if libpng is not present.

OBS Caveat

Conditional BuildRequires are limited to simple variables. RPM usually supports complex constructs like this in an %if expression:

%if 0%(test "%something" = "enabled" && echo 1)

But when evaluating BuildRequires, the RPM parser of the BuildService runs in an environment where subshell expansions are disabled. You'll see warnings like this:

Warning: spec file parser line 109: can't expand %(...)

%lua scripts are not interpreted by the dispatcher either; no warning is emitted.

The following example uses only a simple variable, which works with BuildRequires:

%if ! %{with own_mpfr}
BuildRequires: mpfr-devel

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.

Also try this command for a list:

osc meta prjconf openSUSE:Factory | egrep '^(Preinstall:|Support:|Required:)'
Preinstall: aaa_base acl attr bash coreutils diffutils
Preinstall: filesystem fillup glibc grep insserv libacl libattr
Preinstall: libbz2-1 libgcc%{gcc_version} libxcrypt m4 libncurses5 pam
Preinstall: permissions libreadline6 rpm sed tar zlib libselinux1
Preinstall: liblzma5 libcap2 libpcre0
Preinstall: libpopt0 libelf1 liblua5_1
Required: gcc gcc%{gcc_version} glibc perl rpm tar patch
Support: autoconf automake binutils bzip2 gcc gcc%{gcc_version}
Support: gettext-runtime glibc libtool perl rpm zlib
Support: libncurses5
Support: libaudit1 cpio cpp cpp%{gcc_version} cracklib cvs
Support: file findutils gawk gdbm gettext-tools
Support: glibc-devel glibc-locale groff gzip info less
Support: libbz2-devel libdb-4_8
Support: libstdc++%{gcc_version}
Support: udev
Support: libxcrypt libzio
Support: linux-glibc-devel make man netcfg
Support: net-tools pam-modules patch perl-base sysvinit-tools
Support: texinfo timezone util-linux libmount1 login
Support: libgomp%{gcc_version} libuuid1 psmisc
Support: terminfo-base update-alternatives pwdutils build-mkbaselibs
Support: brp-check-suse post-build-checks rpmlint-Factory
Support: build-compare
Support: libunwind libunwind-devel


Whenever possible, openSUSE packages should avoid conflicting with each other. Unfortunately, this is not always possible. For full details on openSUSE Conflicts policy, see: openSUSE:Packaging conflicts .


SUSE's RPM supports the Recommends tag, but it was not available upstream until very recently. As a result, packages with Recommends will fail to build for OBS targets Fedora_18, RHEL_6 and CentOS_6, for example. A workaround is to exclude the Recommends tag from non-SUSE targets:

%if 0%{?suse_version}
Recommends: foo

Alternatively the Recommends tag could become a Requires tag so that a recommended package (foo) gets installed in any case on systems that do not support RPM Recommends:

%if 0%{?suse_version}
Recommends: foo
Requires: foo

See also openSUSE:Build Service cross distribution howto

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.


All patches in openSUSE spec files SHOULD have a comment above them about their status. For details see Packaging Patches guidelines page.

Preparation Section (%prep)

These are the rules for the preparation section of the specfile.

Quiet %setup

You should pass the -q option to the %setup macro. This will reduce the size of the build logfile significantly, especially with source archives that extract a lot of files.

Build Section (%build)

These are the rules for the build section of the specfile.

Compiler flags

Compilers used to build packages should honor the applicable compiler flags set in the system rpm configuration. In practice, this means %{optflags} (variable: $RPM_OPT_FLAGS, see above) 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 is 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.

Parallel make

Whenever possible, invocations of make should be done as


%make_build is a macro that is available starting rpm-4.12. It is equivalent to

make %{?_smp_mflags}

You should use this expansion directly if you are building with versions of rpm older than 4.12 (which is the case for almost everything right now, including openSUSE 13.2).

This generally speeds up builds, especially on SMP machines. It is much preferable to make %{?jobs:-j%jobs}, as the former allows alternate make flags to be used, such as make -lN, and not hardcoding -jN. Do make sure, however, that the package builds cleanly this way; some make files do not support parallel building, or have broken dependencies.

In case a source package does not support parallel building, please consider explicitly writing -j1 to facilitate grepping for such packages among a group of specfiles. There may be other reasons to use -j1, for example due to otherwise excessive memory usage. (Such occurs for example when building Boost for MINGW.) The common workers on build.opensuse.org have only 2 GB RAM assigned as of September 2013. In any case, consider adding a comment saying what led to the use of -j1, whether it is due to broken dependencies, or memory requirements, etc.

Install Section (%install)

These are the rules for the install section of the specfile.

Since rpmbuild is run as an unprivileged user, running `make install` must not attempt to chown the files (either by running chown directly, or by utilizing, for example, `install -o root...`). File ownership shall be set in the later %files section instead.

%make_install is a macro available starting rpm-4.10. It is equivalent to `make install DESTDIR="%{?buildroot}"`. Should you be using an older rpm (which is the case for SLE_11), use the expansion directly.

There is also a second, similarly-named and therefore confusing ancient macro, %makeinstall (note: no underscore). Avoid using this. In attempt to work with broken software, this macro expands to a very long line which sets all variables to %buildroot plus their final paths, but does not set DESTDIR itself, which causes certain broken software to actually fail then.

For the record, an example of such is xapian-core-1.2.17, where:

# configure.ac contains:
# include/Makefile.mk contains:
inc_HEADERS = include/xapian.h

With this, %makeinstall's expansion, "make install ... includedir=/buildroot/usr/include" has no effect since the awkard Makefile requires incdir to be set instead of includedir. Because %makeinstall does not set DESTDIR, xapian-core will try to install xapian.h to the default location, /usr/include, rather than /buildroot/usr/include. A double failure, so to say.

SUSE's rpm, i.e. /usr/lib/rpm/suse_macros redefines %makeinstall to be the same as (the expansion of) %make_install, but as it is conceivable that your specfile may be used on other distro targets, it is best to avoid %makeinstall, and only ever use %make_install or its expanded form.

Removing the buildroot

openSUSE marks it as bad coding style to have rm -rf %{buildroot} (or rm -rf $RPM_BUILD_ROOT) at the beginning of an %install section like this:

rm -Rf "%buildroot"
mkdir -p "%buildroot/%_prefix/..."  or make install


%{buildroot} is normally within /var/tmp and you just opened a trivial race condition to a local attacker on your machine to take over your account (or event root if you build as root). It is better not to `rm -rf %{buildroot}` in %install at all (and rely on %clean to do it).

If you want to clean it, better do:

rm -Rf "%buildroot";
mkdir "%buildroot";
mkdir -p "%buildroot/%_prefix/..." or make install

In this case the `mkdir %buildroot` would fail and the build would abort if an attacker tries to replace the buildroot by his own symlink.

Clean Section (%clean)

The %clean section, if specified, will be run after the binary and source RPMs have been generated. In the Open Build Service, this section is not necessary because chroots and/or VM environments that are used to build the package are generally torn down anyway. Building packages in environments not started from scratch is usually not supported for openSUSE packages (cf. bnc#176528 c4)

Starting with rpm-4.7/openSUSE_11.3, rpm defaults to "%clean: rm -Rf %{buildroot}" if the %clean section is completely absent from the specfile.

In the distant past, some packages, in %clean, checked that %{buildroot} was not / before deleting it. This is not necessary in openSUSE anymore.

Scriptlets (%post* / %pre*)

These are the rules for the scriptlet sections of the specfile. Great care should be taken when using scriptlets. If scriptlets are used, those scriptlets must be sane. Some common scriptlets are documented in openSUSE:Packaging scriptlet snippets.

Scriptlets requirements

Your package has to require everything you use in scriptlets. The notation is as follows:

Requires(pre): ...
Requires(post): ...

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 (valid?) 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.

Files Section (%files)

These are the rules for the files section of the specfile. openSUSE follows the Filesystem Hierarchy Standard with regards to filesystem layout. The FHS defines where files should be placed on the system. Any deviation from the FHS should be rationalized as a comment in the spec file.


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. 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 is 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 where
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.

An openSUSE package must not contain any duplicate files in the %files listing, both in the sense of one file packaged twice or more (in two or more subpackages), and in the sense of content. Run %fdupes %buildroot (requires adding BuildRequires: fdupes) to smartly elimiate duplicate content by replacing those files with hardlinks to one another.


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:


Unless you have a very good reason to deviate from that, you should use %defattr(-,root,root) for all %files sections in your package. You can use %defattr(-,root,root,0755) to fix permission issues with directories. E.g. when an umask was too tight while unpacking.

SUID bits

Security-relevant permissions are handled via /etc/permissions* on openSUSE. Read the files /etc/permissions* to learn about the basics.

If you want to create a package with suid programs, you do the following:

  • Consider first, if you really need it. Usually using setuid bits is insecure and shows that you do not have well thought out design.
  • Add a Requires(post): permissions header to your spec file.
  • In the %files section, define the attributes of the files listed in your permissions files as they are defined for permissions.secure. Instruct rpmverify to not check ownership or permissions.
  • Add a %post scriptlet that sets your package's permissions according to the system's current security level.
  • Add a %verifyscript scriptlet that checks your package's permissions according to the system's current security level.

And because the above contains a few non-obvious details, here's a stripped down example:

PreReq:         permissions

%if 0%{?suse_version} >= 1120
%verify_permissions -e %_bindir/mysuidprogram

%if 0%{?set_permissions:1}
    %set_permissions %name

%verify(not user group mode) %attr(0711,root,root) %_bindir/mysuidprogram

If you create new setuid bits programs and want to have them included into the openSUSE distribution, they must be audited by the SUSE Security Team. Open a bugreport assigned to security-team@suse.de and/or send an e-mail to security@suse.de

To do temporary builds in your home project:

  • Use the package-specific permissions that can be defined through files in /etc/permissions.d/.
  • Create permissions{,.easy,.secure,.paranoid} files for your package. permissions is used if no file permissions.* matching the system's current security setting is found. As a rule of thumb, permissions.easy should contain permissions as installed by make install, permissions.paranoid should remove all suid bits (even if this breaks functionality), and permissions.secure can be something inbetween.
  • Add these permissions files as sources to the spec file, and have %install install them in %buildroot/%_sysconfdir/permissions.d/packagename[.suffix].
  • In order to avoid rpmlint's error messages about disallowed permissions files, create a file packagename-rpmlintrc containing the line setBadness('permissions-unauthorized-file', 333), and list it as a Source in your spec file. (Modify the "333" if you have fewer or more than 3 disallowed files.)

Please note that all these workarounds have to go before you submit to the openSUSE distribution.

Documentation files

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. Also pay attention about which subpackage you include documentation in, for example API documentation belongs in the -devel subpackage, not the main one. Or if there is a lot of documentation, consider putting it into a subpackage of its own. 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.

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 would not work with the config file from the previous package revision. Whenever plain %config is used, add a brief comment to the specfile explaining why.

Do not use %config or %config(noreplace) under /usr. /usr is deemed to not contain configuration files in openSUSE.

Development files

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.
  • pkgconfig files. A reasonable exception is when the main package itself is a development tool, e.g. gcc or gdb.

Packages containing pkgconfig (.pc) files must utilize BuildRequires: pkg-config so that the proper runtime dependency Requires: pkg-config is added.

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. 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_lang is much easier in the spec file than having to do:
  • As new locale files appear in later package revisions, %find_lang will automatically include them when it is run, preventing you from having to update the spec any more than is necessary.
  • To include the locale files found by %find_lang you have add the -f %{name}.lang option to the %files section. So the section header should look like %files -f %{name}.lang.

Non-ASCII Filenames

Filenames that contain non-ASCII characters must be encoded as UTF-8. Since there is 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.


The Filesystem Hierarchy Standard does not include any provision for libexecdir, but openSUSE packages can store appropriate files there. Libexecdir (which is redefined to /usr/lib on openSUSE systems) should be used as the directory for executable programs that are designed primarily to be run by other programs rather than by users. openSUSE 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.

Changelog section (%changelog)

See HOWTO write good changes