When building RPM packages, we often encounter situations where our software needs either PackageA or PackageB to function, but not necessarily both. The RPM packaging system doesn't natively support this "OR" dependency syntax in spec files, which creates interesting technical challenges.
The standard RPM spec file uses simple dependency declarations:
Requires: package-a
Requires: package-b
This creates an AND relationship where both packages must be installed. What we need is a way to express:
Requires: package-a >= 1.0 OR package-b >= 2.0
Option 1: Virtual Packages (Preferred when possible)
# In package-a.spec:
Provides: virtual-feature = %{version}
# In package-b.spec:
Provides: virtual-feature = %{version}
# In your package.spec:
Requires: virtual-feature
Option 2: Conditional Requires (Using %if)
%if 0%{?rhel} >= 7
Requires: package-a
%else
Requires: package-b
%endif
When you don't control both packages, a runtime check in %pre might be necessary:
%pre
if ! rpm -q --quiet package-a && ! rpm -q --quiet package-b; then
echo "Error: Either package-a or package-b must be installed" >&2
exit 1
fi
For maintaining proper dependency tracking while still allowing flexibility:
%post
if rpm -q --quiet package-a; then
rpm --setdeps --requires package-a
elif rpm -q --quiet package-b; then
rpm --setdeps --requires package-b
fi
Here's how you might handle alternative graphics backends:
# In your package.spec
Requires: mesa-libGLU | nvidia-libGLU
%pre
if ! rpm -q --quiet mesa-libGLU && ! rpm -q --quiet nvidia-libGLU; then
echo "Either mesa-libGLU or nvidia-libGLU required" >&2
exit 1
fi
- Always document your OR dependencies in package descriptions
- Consider creating a meta-package that pulls in one of the alternatives
- Test both dependency paths thoroughly
- Be aware of potential version conflicts between alternatives
When building RPM packages, we often encounter situations where our software can work with multiple alternative dependencies, but the standard RPM spec syntax doesn't provide a native way to express "this OR that" dependencies. This limitation forces package maintainers to make suboptimal choices between:
- Requiring one specific package (potentially excluding valid alternatives)
- Circumventing RPM's dependency system with manual checks
- Creating artificial virtual packages
The RPM packaging system provides several dependency directives:
Requires: package
Recommends: package
Suggests: package
Conflicts: package
However, it lacks Boolean operators (OR, AND, NOT) in dependency specifications. The closest native alternative is using virtual provides:
# In foo-bar.spec
Provides: virtual-foobar = %{version}
# In bar-foo.spec
Provides: virtual-foobar = %{version}
# In your package
Requires: virtual-foobar
Option 1: Runtime Detection in %pre Script
This approach validates dependencies during installation but doesn't register them in RPM's database:
%pre
if ! rpm -q --quiet foo-bar && ! rpm -q --quiet bar-foo; then
echo "Error: Either foo-bar or bar-foo must be installed" >&2
exit 1
fi
Option 2: Weak Dependencies with Recommends
For newer RPM versions (4.13+) supporting weak dependencies:
Recommends: foo-bar
Recommends: bar-foo
Option 3: Virtual Package with Fallback
When you control one of the packages:
# In bar-foo.spec
Provides: foobar-compatibility = %{version}
# In your.spec
Requires: foobar-compatibility
For complex scenarios, you can modify RPM's database in %post (use with caution):
%post
if rpm -q --quiet foo-bar; then
rpm --setdeps --requires "foo-bar" %{name}-%{version}-%{release}
elif rpm -q --quiet bar-foo; then
rpm --setdeps --requires "bar-foo" %{name}-%{version}-%{release}
fi
After extensive testing across various distributions, I recommend:
- Prefer virtual packages when possible
- Use runtime checks only as last resort
- Document alternative dependencies clearly in package descriptions
- Consider creating a compatibility meta-package if you control the ecosystem
For critical systems, the safest approach remains requiring a specific default package while supporting alternatives at runtime through configuration files or environment variables.