EPEL Packaging

This page contains guidelines which are not relevant or are no longer relevant to Fedora, but still apply to EPEL packages. These guidelines are designed to avoid conflict with the larger Fedora Packaging Guidelines, but should any conflicts occur, these guidelines should take precedence on EPEL packages.

As a reminder, these guidelines only apply to EPEL packages, not to Fedora packages.

Package Dependencies

All EPEL package dependencies (build-time or runtime) MUST ALWAYS be satisfiable within the Target Base (as defined by EPEL Policy) or EPEL itself. Weak package dependencies are allowed on packages from other RHEL channels that are not part of the Target Base, such as the HighAvailability or ResilientStorage channels. This allows for repoclosure with only the Target Base, but allows EPEL packages to pull in other packages via weak dependencies when additional channels are enabled.

This does not mean that EPEL packages should incorrectly identify a dependency as weak (e.g. changing a Requires to a Recommends). On a case by case basis, exceptions to this policy may be granted by the EPEL Steering Committee. To request an exception open an issue and add the "meeting" tag.

Limited Arch Packages

See Missing RHEL Sub-Packages

ELN

ELN is a new buildroot and compose process for Fedora that takes Fedora Rawhide dist-git sources and emulate a Red Hat Enterprise Linux compose. The packages included are thus based on what is planned to be included in the next major RHEL release, and in that way it is already useful for EPEL packagers.

ELN Extras, however, is an extension that is mostly driven by EPEL packagers. Given that one of the pain points in bootstrapping a new EPEL is in processing the dependency graph of the packages our packagers are actually interested in (whether they are a library that some in-house or ISV software needs, or a tool) and getting them branched and built, we can use ELN Extras in this way:

  • add packages to ELN Extras' content resolver input, e.g. KDE packages; note that this has sufficient metadata to indicate who will maintain such packages

  • check the dependencies pulled in

The former list is what packagers actually care about, the latter is just what needs to be brought in.

EPEL 8

Scriptlets

Fedora has been moving towards the use of file triggers and away from requiring that packagers cut and paste scriptlets into loads of packages. At the time of this writing, we are trying to backport all of these to EPEL8, so that fedora packages are easily able to build on EPEL8 without any changes. When EPEL 8 becomes old enough, that these backports are not feasible and/or wanted, we will list them here.

EPEL 7

Rich Dependencies

RHEL 7’s rpm and yum versions do not support rich or boolean dependencies, so these are not allowed in EPEL 7.

RPM Macros

Not all macros defined in (or built into) existing Fedora packages will work when a spec is converted for use in EPEL. epel-rpm-macros backports the newer macros and is installed by default in EPEL mock chroots.

Scriptlets

Fedora has been moving towards the use of file triggers and away from requiring that packagers cut and paste scriptlets into loads of packages. These scriptlets would still be needed for EPEL, and as scriptlets are no longer needed in any Fedora release, they’re moved here.

Shared Libraries

On EPEL 7 and older, ldconfig MUST be called properly in order to regenerate the dynamic linker’s cache. If the package or subpackage has no existing %post or %postun scriptlets, simply include the %ldconfig_scriptlets macro on its own line before the %files list.

[...]
%install
# Install the program

%ldconfig_scriptlets libs

%files libs
%license GPL
[...]

Using the %ldconfig_scriptlets macro will automatically generate a dependency on ldconfig where necessary. The macro will do nothing at all in Fedora.

If the package or subpackage already has existing %post or %postun scriptlet, then use of %ldconfig_scriptlets will cause an error. You can use %ldconfig_post or %ldconfig_postun individually to generate a scriptlet which doesn’t already conflict.

Within an existing %post or %postun scriptlet, use %{?ldconfig} on its own line to call ldconfig on those releases which need it. This will do nothing when not needed. When calling ldconfig in this way, you MUST also have the proper dependency on /sbin/ldconfig: Requires(post): /sbin/ldconfig and/or Requires(postun): /sbin/ldconfig as appropriate. (This will generate an unnecessary dependency on releases which do not strictly need it, but this does no harm.)

GSettings Schema

GSettings is the configuration system used by the GNOME 3 desktop. It replaces the older GConf system, which was used in GNOME 2. GSettings has pluggable backends, the 'native' one for GNOME is using DConf to store settings. The GSettings API and utilities are part of the glib2 package.

Programs which use GSettings install schema information including default values in the directory %{_datadir}/glib-2.0/schemas. Schema files are xml files with the extension .gschema.xml. At runtime, GSettings uses the schemas in a compiled binary (but arch-neutral) form, which is created by running the glib-compile-schemas utility. /usr/bin/glib-compile-schemas must be run whenever the set of installed schemas changes.

%postun
if [ $1 -eq 0 ] ; then
    /usr/bin/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :
fi

%posttrans
    /usr/bin/glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || :

gdk-pixbuf loaders

gdk-pixbuf is a library that is part of the gdk-pixbuf2 package. It is for loading images in various formats in GNOME. gdk-pixbuf can be extended by implementing loaders for image formats in loadable modules. These loadable modules have to be installed in %{_libdir}/gdk-pixbuf-2.0/2.10.0/loaders. To avoid opening all modules in that directory unnecessarily, gdk-pixbuf maintains a cache with information about the available modules in the text file %{_libdir}/gdk-pixbuf-2.0/2.10.0/loaders.cache. This cache file needs to be updated when the set of installed modules changes, by calling the /usr/bin/gdk-pixbuf-query-loaders binary. Multilib considerations force us to install the binary in -32 and -64 variants.

The scriptlets to maintain the cache file are:

%postun
    /usr/bin/gdk-pixbuf-query-loaders-%{__isa_bits} --update-cache &> /dev/null || :

%post
if [ $1 -eq 1 ] ; then
    # For upgrades, the cache will be regenerated by the new package's %postun
    /usr/bin/gdk-pixbuf-query-loaders-%{__isa_bits} --update-cache &> /dev/null || :
fi

Note the use of %{__isa_bits}, which is an rpm macro that expands to either 32 or 64, depending on the architecture of the package.

GTK+ modules

The GTK+ toolkit (in the gtk3 package) can be extended by loadable modules which can provide theme engines, input methods, print backends or other functionality. These modules have to be installed in subdirectories of %{_libdir}/gtk-3.0 or %{_libdir}/gtk-3.0/3.0.0. For the input methods, GTK+ maintains a cache in the text file %{_libdir}/gtk-3.0/3.0.0/immodules.cache. This cache file needs to be updated when the set of installed input methods changes, by calling the gtk-query-immodules-3.0 binary. Multilib considerations force us to install the binary in -32 and -64 variants.

The scriptlets to maintain the cache file are:

%postun
/usr/bin/gtk-query-immodules-3.0-%{__isa_bits} --update-cache &> /dev/null || :

%post
if [ $1 -eq 1 ] ; then
    # For upgrades, the cache will be regenerated by the new package's %postun
    /usr/bin/gtk-query-immodules-3.0-%{__isa_bits} --update-cache &> /dev/null || :
fi

The 3.0 in the binary name is there because gtk2 has its own utility for the same purpose, called gtk-query-immodules-2.0. Note the use of %{__isa_bits}, which is an rpm macro that expands to either 32 or 64, depending on the architecture of the package.

GIO modules

GIO is a library that is part of the glib2 package. It is a low-level part of the GNOME stack. GIO can be extended by implementing extension points in loadable modules. These loadable modules have to be installed in %{_libdir}/gio/modules. To avoid opening all modules in that directory unnecessarily, GIO maintains a cache with information about the available modules in the text file giomodule.cache in the same directory. This cache file needs to be updated when the set of installed modules changes, by calling the gio-querymodules binary. Multilib considerations force us to install the binary in -32 and -64 variants.

The scriptlets to maintain the cache file are:

%postun
/usr/bin/gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules &> /dev/null || :

%post
# We run this after every install or upgrade because of a cornercase
# when installing the second architecture of a multilib package
/usr/bin/gio-querymodules-%{__isa_bits} %{_libdir}/gio/modules || :

Note the use of %{__isa_bits}, which is an rpm macro that expands to either 32 or 64, depending on the architecture of the package.

mimeinfo

Use this when a package drops an XML file in %{_datadir}/mime/packages.

%post
/bin/touch --no-create %{_datadir}/mime/packages &>/dev/null || :

%postun
if [ $1 -eq 0 ] ; then
  /usr/bin/update-mime-database %{_datadir}/mime &> /dev/null || :
fi

%posttrans
/usr/bin/update-mime-database %{?fedora:-n} %{_datadir}/mime &> /dev/null || :

Note that similarly to the gtk-update-icon-cache code, these scriptlets should be run only if the user has update-mime-info installed and without a specific Requires: shared-mime-info. If shared-mime-info is not installed, update-mime-database won’t be run when this package is installed. This does not matter because it will be run when the shared-mime-info package is installed.

desktop-database

Use this when a desktop entry has a MimeType key.

%post
/usr/bin/update-desktop-database &> /dev/null || :

%postun
/usr/bin/update-desktop-database &> /dev/null || :

Note: This scriptlet follows the same convention as mimeinfo files and gtk-icon-cache. Namely, the spec file should not Require desktop-file-utils for this. For older releases, one should

Requires(post): desktop-file-utils
Requires(postun): desktop-file-utils

Icon Cache

If an application installs icons into one of the subdirectories in %{_datadir}/icons/ (such as hicolor in the following examples), icon caches must be updated so that the installed icons show up in menus right after package installation. This consists of updating the timestamp of the top-level icon directory where the icons were installed, and running gtk-update-icon-cache. 'touch’ing the top-level dir is done so that environments compatible with the Icon theme specification can refresh their caches, and gtk-update-icon-cache which is additionally required for GNOME also does its work based on the dir timestamp.

Note that no dependencies should be added for this. If gtk-update-icon-cache is not available, there’s nothing that would be needing the cache update, ditto if "touch" is not available, there’s nothing that would benefit from icon cache updates installed yet either. Not adding the dependency on gtk-update-icon-cache (i.e. gtk2 >= 2.6.0) or "touch" makes it easier to use the package (or the same specfile) on systems where it’s not available nor needed, such as older distro versions or (very) trimmed down installations, and generally results in less entries in specfiles, rpmdb, and repo metadatas.

%post
/bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null || :

%postun
if [ $1 -eq 0 ] ; then
    /bin/touch --no-create %{_datadir}/icons/hicolor &>/dev/null
    /usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
fi

%posttrans
/usr/bin/gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :

Python

The Fedora Python Packaging Guidelines underwent a major overhaul in 2021. The macros used in these guidelines are also available in RHEL 9. EPEL 9 Python packages SHOULD use these guidelines. EPEL 9 Python packages MAY use the older 201x-era Fedora Python Packaging Guidelines. EPEL 7 and EPEL 8 Python packages MUST use the older guidelines. Python 2 packages should also refer to the Python 2 section of the Fedora Python Packaging Appendix. New Python 2 packages SHOULD NOT be added to EPEL 8, because the RHEL 8 Python 2.7 Application Stream will be retired in June 2024.

Automatically generated dependencies

The Python run-time dependency generator mentioned in the Fedora Python Packaging Guidelines is enabled by default for EPEL 8 and EPEL 9 builds. EPEL 7 packages must explicitly list run-time dependencies.

The dependency generator in RHEL 8 is significantly limited compared to the one in Fedora and RHEL 9. Simple dependencies and minimum/maximum versions work correctly, but more advanced specifications such as environment markers and compatible release clauses do not. This can lead to missing dependencies, included dependencies that should have been skipped, or other incorrect behavior. The packager MUST inspect the generated requires for correctness. If the software uses an advanced dependency specification that does not parse correctly, the packager MUST ensure the dependency is included. This can be done either by patching the source to achieve the desired result from the generator, or by using an explicit Requires: statements.