35

Does anyone know how to (or whether one can) specify an alternate requirement or set of requirements in a spec file, as opposed to a single requirement?

For example, say there are two packages available, conveniently named foo-bar and bar-foo. My package requires one of these but not both, and I don't care which one is present. At runtime I use whichever is available.

So effectively I would like a way to say:

Requires: foo-bar OR bar-foo

As far as I can tell that's not possible, but I figure there are people here who know a lot more about RPM than I do, so maybe there's a way to do it.

UPDATE: I only control the packaging of bar-foo, not foo-bar, so having both provide a virtual package won't work.

UPDATE: The thing I actually need is itself a virtual package inside each of the packages. Say foo-bar provides eagle' andbar-foo provides beagleand my package works with either (or both); but other packages require eithereagleorbeagleorfoo-barorbar-foo`, and the target system can have either or both installed.

I'm currently leaning towards solving this with a %pre script that does something like:

rpm -q eagle || rpm -q beagle || echo "need eagle or beagle" && /bin/false

While I'm pretty sure that would work, it seems like a brutal circumvention of RPM's dependency tracking. For instance you'd never see my package when you asked whatrequires foo-bar or whatrequires beagle.

UPDATE: On second thought, the pain of requiring people to install foo-bar where they might not is less than the pain of circumventing RPM dependency management, at least for my situation. So unless somebody comes up with a way to properly require "this OR that" (which I think would be a great feature to have in RPM generally) then I plan to require only foo-bar and then, at runtime, if bar-foo is available I will choose between them according to whatever criteria I need.

UPDATE: another idea, which would also be cheating RPM but might get things into the right state. Maybe I could, in %post, fiddle with RPM's database directly. Thus %pre could protect me from an invalid install, and %post would retroactively tell RPM that I require either foo-bar or bar-foo or both, depending on what's there when I install.

Thanks for the suggestions!

Kevin Frost
  • 451
  • 1
  • 4
  • 4
  • I know this is very old; but is there a good solution now for this? I am making an RPM which has java-1.6.0-openjdk in Requires: line; but with java7; I would like to support java-1.7.0-openjdk as well but could not figure out a good way to put either of those two in Requires: – vpram86 Aug 22 '13 at 08:48
  • If you control packaging of bar-foo, one possible solution is to build it with `Provides: foo-bar`, so it satisfies both dependencies. For newer rpm versions, check [Boolean Dependencies](http://www.rpm.org/wiki/PackagerDocs/BooleanDependencies). Stay away from `%pre` and `%post` sections, [don't try to defeat the system](https://docs.fedoraproject.org/en-US/Fedora_Draft_Documentation/0.1/html/RPM_Guide/ch-packaging-guidelines.html#id670752). – forcefsck Feb 08 '16 at 15:09

5 Answers5

16

This is now possible as of RPM 4.13.

https://rpm-software-management.github.io/rpm/manual/boolean_dependencies.html

It can be just simple as: Requires: (pkgA >= 3.2 or pkgB)

Graham Leggett
  • 208
  • 2
  • 10
carlwgeorge
  • 514
  • 3
  • 10
  • from the document it looks like these can not be used with requires, only the 'weak' dependencies correct? – dsollen May 22 '17 at 17:58
  • The second link shows that they can be used with Requires. The first link does mention that using it that way isn't allowed in Fedora, but that won't apply to custom packages. – carlwgeorge May 22 '17 at 18:32
9

This kind of behaviour is already done by several packages, for example mail transport agents. Those virtual packages provide your system a way to know if a capability they need is already provided by some other program.

See if virtual packages example in rpm.org helps you.

dimir
  • 105
  • 4
Janne Pikkarainen
  • 31,454
  • 4
  • 56
  • 78
  • Thanks. I don't think virtual packages will solve my specific problem here, but I agree they are very useful. In my case I don't want to require some common feature provided by both `foo-bar` and `bar-foo`, and since I don't control the packaging of `foo-bar` I can't just make them both provide `support-for-mypackage`. If I controlled the packaging of both alternate prerequisites then indeed a shared virtual package would be a great solution. – Kevin Frost Aug 09 '11 at 13:30
5

Two possibilities:

If the part of foo-bar and bar-foo you use is a common file you can just Require /path/to/file (I think so; my testing was limited).

Your situation is similar to optional dependencies. The way they are handled is to have a X-common package and then have a X-foo-bar package that requires foo-bar and an X-bar-foo package that requires bar-foo.

Mark Wagner
  • 17,764
  • 2
  • 30
  • 47
  • There are no common files, unfortunately. That would be a cool trick if there were, though also potentially dangerous: some future version of `foo-bar` could move its files around (I only control `bar-foo` here). Optional dependencies are interesting but not quite what I need, since I really do need _either_ `foo-bar` _or_ `bar-foo`; the only thing optional is the choice of which. Thanks for replying. – Kevin Frost Aug 10 '11 at 17:15
  • This solved my issue! Different GNU/Linux flavors provide different python3 virtual packages: python3, python34, python35, etc. In order for my single package to work on all of them, I was able to just use `Require: /usr/bin/python3` – bgStack15 Dec 01 '16 at 12:49
0

Will it work for you to have your package bar-foo provide the virtual package foo-bar?

You can then just make your burp-baz package require foo-bar.


If doing the above feels skeezy (it probably is) you may need to create two versions of your RPM, one depending on foo-bar and the other depending on bar-foo.
MikeyB
  • 38,725
  • 10
  • 102
  • 186
  • Tempting, but dangerous: something else, which really does need `foo-bar`, would then break if it thought `bar-foo` was providing something it really wasn't. The sticking point is that for *my* package I need *either* of the prerequisites but not both; but any other package might really need just one of them. And I can't just require both either, since there are real cases where only one or the other will be available. – Kevin Frost Aug 09 '11 at 18:16
-2

Non-determinism in automated systems (which is either dependency management or the machines that use RPMs) is a really bad thing. You WANT it to fail on a this-or-that situation, as failing is still not as bad as an unexpected outcome.

To solve the issue, maybe have the package you DO control %provide the main tokens that the immutable package also happens to %provide and which your other software %depends; then have your package %obsoletes the immutable one. Especially if it's already in place, you may get it winning out over the other install.

Packaging and proper dependency and install operations is tricky work. The goal - reliable, repeatable, auditable installs - is so valuable that you may realize the gains of getting it right.

Dependency hell is self-inflicted. No exceptions

user2066657
  • 336
  • 2
  • 13
  • Here's the fish I'll give to you: You need only one of the two because both provide some file or resource. So, don't %depend on the name of the package, just on the file or resource they provide. Yes, you'll still be courting non-determinism, but if you're actually considering mucking with the rpmdb directly, you're already gleefully considering risks that most people have learned to avoid. I hope you can find a solution that doesn't incur such technical debt. – user2066657 Aug 25 '16 at 14:56