From Fedora Project Wiki
Warning.png
This page is a draft only
It is still under construction and content may change. Do not rely on the information on this page.

The Problem

rpm and yum treat a dependency on a package of the form Requires: foo as being fulfilled by any available package foo, regardless of arch. On multilib systems such as x86_64, there are often two packages with the same name: one for each of the multilib arches. When yum is asked to satisfy a dependency for that package name it could pull in the package for the wrong arch. This happens when the correct architecture is not available to yum. That might be the case if, due to some malfunction, the Fedora repositories are out of synch. It can also happen if a user has installed a package that is treated as "newer" than the corresponding package in the currently enabled set of repositories; in attempting to resolve otherwise-unresolvable dependency chains, yum may decide to pull in the dependency chain for a different arch.

If a dependency really can be satisfied by a build for any architecture, there's no reason to make the dependency architecture-specific. These are the scenarios where it does matter:

  • A library that is explicitly Required (example a dlopen'd library)
  • The dependency from one -devel packages that is not noarch to another -devel package.
  • A non-noarch subpackage's dependency on its main package or another subpackage (e.g., libfoo-devel depends on libfoo, or fooapp-plugins depends on foo-app).

Packages MUST add the arch specific dependency in those cases.

In most cases, adding an arch specific dependency unnecessarily will not cause problems. There are a few, however, that MUST NOT be made arch specific:

  • A package has a Build-Requires on a specific arch. library (because rpmbuild evaluates the %{_isa} at .src.rpm buildtime, and not at .src.rpm => .arch.rpm build time).
  • Specifying an arch specific dependency on a package that is noarch.

Making Requires Arch-Specific

The way to make a package dependency arch-specific is by appending the macro %{?_isa} to the package name. For instance,

Requires: foo

becomes

Requires: foo%{?_isa}

…full documentation can be seen at the rpm wiki page on Arch requires.

Suggested modifications to the Packaging Guidelines

Requires

[Change the second sentence of paragraph 6 to:]

They're not usually picked up automatically by rpm; and unless the generated RPMs will be noarch, -devel package dependencies on other -devel packages should be arch-specific.

[Change paragraph 7 to:]

A dependency is made arch-specific by appending the macro %{?_isa} to the package name. For example:

 Requires: foo

becomes

 Requires: foo%{?_isa}

This means that gtk+ devel should contain

 Requires: glib-devel%{?_isa} libXi-devel%{?_isa} libXext-devel%{?_isa} libX11-devel%{?_isa}

Explicit Requires

[Append to the first paragraph:]

Explicit library dependencies should typically be arch-specific (unless the packages involved are noarch).

[Change the example for a versioned explicit dependency to:]

 # The automatic dependency on libfubar.so.1 is insufficient,
 # as we strictly need at least the release that fixes two segfaults.
 Requires: libfubar%{?_isa} >= 0:1.2.3-7

Requiring Base Package

[Change to:]

Subpackages are often extensions for their base package and in that case they should require their base package. It is almost always better to over specify the version, so it's best practice to just use a fully versioned dependency: Requires: %{name} = %{version}-%{release}. Devel packages are an example of a package that must require their base packages using a fully versioned dependency. -libs subpackages which only contain shared libraries do not normally need to explicitly depend on %{name} = %{version}-%{release}, as they usually do not need the base package to be functional libraries.

If you end up in a situation where the main package depends on the subpackage and the subpackage on the main package you should think carefully about why you don't have everything in the main package.

When a subpackage requires the base package, it must do so using a fully versioned arch-specific (for non-noarch packages) dependency:

  Requires: %{name}%{?_isa} = %{version}-%{release}

Suggested modifications to the Naming Guidelines

Renaming/replacing existing packages

[Add after paragraph 5:]

Explicit Provides: need to be aware of whether the package is supplying things that can be used in an arch-independent or arch-specific fashion. For packages that are not noarch, Provides: should be made arch-specific by applying the %{?_isa} macro. Packages that explicitly Provide: things that can be used in an arch-independent way—i.e., packages whose dependents don't need to be of the same arch—need not apply this macro. In some cases, a package will supply multiple elements, some of which may be consumed only by dependents of an identical arch and some which may be consumed by dependents of any arch. In such cases, both arch-specific and arch-independent Provides: are warranted.

Examples of packages that should explicitly provide only arch-specific Provides: include native code libraries or plug-ins and their associated -devel packages. Packages that should explicitly provide only arch-independent Provides: include most stand-alone programs (in addition to all noarch packages). Even though these programs may themselves be arch-specific, clients that run them should not care about their arch in most cases. A package that explicitly provides, for example, both a native code library as well as an interpreted language interface to that library should have both arch-specific (for clients of the native code library) and arch-independent (for clients of the interpreted language interface) Provides:.

Question

  • Does the MUST only apply to libraries? Since apps are usually not multilib I'm unclear if they should be included as a MUST or if they fall in the doesn't helo or hurt category.
Mattmccutchen 03:17, 3 June 2010 (UTC)

Both applications and libraries can dlopen modules; and thus the same rules apply when dealing with such a dependency.

If you're asking about depending on applications, the answer is: they usually should not be arch-specific; but it depends. Specifically, there are some conceivable edge cases where it would matter: e.g., my package consumes the output of a program whose output varies depending on the arch.

Braden 3:55, 19 June 2010 (UTC)
  • Added specifying an arch specific dep on a noarch package as causing problems. Is that true?
Mattmccutchen 03:17, 3 June 2010 (UTC)

I'm pretty sure it is, since the arch of a noarch package is "noarch"; and thus nothing else is going to match. And while it's accurate that an unnecessary arch-specific Require is unlikely to be harmful (as long as it actually resolves to something), I'd prefer to avoid wording that might lead folks to think that it's okay to naively make their Requires arch-specific "just in case".

Braden 3:55, 19 June 2010 (UTC)
  • If we don't use arch-specific BuildRequires, then there is nothing preventing the same kinds of problems from happening as with Requires (although maybe they are less frequent with mock usually starting from a minimal buildroot). We ought to find a way to get the BuildRequires evaluated properly for each architecture. Some possible approaches:
    1. For each architecture, rebuild the SRPM first (a relatively cheap operation) and then query it.
    2. Add a new query tag so that "rpm -q --specfile" can query BuildRequires, and then use that for each architecture.
Mattmccutchen 03:17, 3 June 2010 (UTC)

I'm less concerned with this case because it doesn't impact Fedora end users the same way. If Fedora's package build system pulls down the wrong build dependency, then presumably the build fails. The package maintainer then waits for the system to right itself and then tries again. By contrast, Requires that aren't properly arch-specific can result in users getting packages that don't work together. So I'd prefer to address the issue of BuildRequires separately."

Braden 3:55, 19 June 2010 (UTC)

There is rpmbuild option --target which no longer works if BuildRequires have no %{_isa}. If you mean it seriously you have to remove the rpmbuild --target option first. It is a regression, I have been using it for many years and it saves a lot of engineering time during .spec files debugging than having to deal with mock each time - just because of this regression."

Jankratochvil 18:35, 23 Feb 2012 (CET)