Bug 203080 - RPM should allow for arch-specific Obsoletes / Requires
Summary: RPM should allow for arch-specific Obsoletes / Requires
Keywords:
Status: CLOSED DUPLICATE of bug 235755
Alias: None
Product: Fedora
Classification: Fedora
Component: rpm
Version: 6
Hardware: All
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Paul Nasrat
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2006-08-18 12:19 UTC by Brian Long
Modified: 2007-11-30 22:11 UTC (History)
2 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2007-08-07 11:22:57 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)

Description Brian Long 2006-08-18 12:19:56 UTC
Description of problem:
If you look back at the Fedora Core 3 perl.i386 issue
(https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=156288), you'll see
comment #12 mentions that "Obsoletes: perl.i386" could have fixed the issue if
rpm supported such syntax.

Version-Release number of selected component (if applicable):
rpm-4.4.2-31.i386.rpm

Please consider adding a feature for RPM on bi-arch platforms (i.e. x86_64 and
ia64) that would allow arch-specific Obsoletes and Requires.

Comment 1 Jeff Johnson 2006-08-18 15:26:06 UTC
Try adding a file based Obsoletes:. E.g. if i386 installs libfoo.so in /lib, while x86_64 installs in /lib64,
then a arch-based obsolete can be achieved by doing
    Obsoletes: /lib/libfoo.so
to the x86_64 package to obsolete the package that contains (i.e. the i386 pkg) /lib/libfoo.so

In general, multilib packages should not be aware of other packages with different arches, and
any case in which there is a need for, say, i386 packages to be aware of the existence of
x86_64 packages is likely to be a packaging, not an rpm implementation, problem.

WONTFIX

Comment 2 John Haxby 2006-09-06 18:11:30 UTC
I think this needs be to re-considered.  I have a package here that depends on
cyrus-sasl-md5 in order to be able to provide CRAM-MD5 SASL authentication.

The shared library that implements CRAM-MD5 is loaded at run time by the
cyrus-sasl library.  If I put in a dependency on cyrus-sasl-md5 then it's
satisfied by both the i386 and x86_64 RPMs, but only one of these will actually
do :-)   It's in the nature of cyrus-sasl that only it knows the name of the
shared library that implements CRAM-MD5.

In general if you depend on a package for a plug-in (cyrus-sasl and PAM plug-ins
both spring to mind here) then there isn't a good way to specify the dependency.
 If you specify a file that's part of the plug-in then you're assuming more
about the implementation than you should do.

To be honest, the cyrus-sasl-md5 should offer a feature (eg "sasl-crammd5")
which I should depend upon so that I don't require a particular implementation.
 And in this case, I definitely couldn't specify a filename!

Comment 3 Jeff Johnson 2006-09-06 23:16:55 UTC
Even if the shared library is "loaded at run time", the paths to
the ELF64 and ELF32 libraries are different, so ut is possible to
use
    Obsolete: /path/to/runtime/loaded/library
to remove the package of the other persuasion if you insist.

I have stated the general reason why packages built for different
arches must not know about each other, and give you a work around
for Obsoletes:. Add a Requires: file dependency on the different
paths if you need to depend on arch specific runtime loadable modules.

Reconsidered.

WONTFIX

Comment 4 John Haxby 2006-09-07 09:15:41 UTC
That was a rubbish comment from me.  I blame it on being done late att night :-)

There are a couple of use-cases that I can think of where putting a dependency
on a file name doesn't work.

First, if I have

   Requires: /usr/lib/sasl2/libdigestmd5.so

in my spec file then this works fine.  A "yum localinstall" will pull in
cyrus-sasl-md5 which is exactly what I want.  However, suppose the cyrus-sasl
folks decide to implement DIGEST-SHA1 and, since there's so much code in common,
decide that actually it can all go in a library called
"/usr/lib/sasl2.libdigest.so" which provides both the DIGEST-MD5 and DIGEST-SHA1
mechanisms.   My program(s) won't care, they don't know the name of the files
that get loaded to provide SASL authentication mechanisms and the functionality
will be exactly as it was before (apart from the extra SASL mechanism). 
However, you won't be able to install the new cyrus-sasl RPMs because there's a
dependency on a file that no longer exists.  And no, you can't symlink
libdigestmd5.so to libdigest.so because you'll get the mechanisms in that shared
library twice which looks pretty silly :-)

The second use case is slightly different.  Suppose we have a new SASL mechanism
which, for the sake of argument, I'll call "MYMECH".  There are several possible
implementations of this and my program doesn't care which implementation it gets
so I'll put "Provides: SASL-MYMECH" in the MYMECH spec file and "Requires:
SASL-MYMECH" in the program's spec file.  Now I'm in trouble.  The "Requires:"
header line will be satisfied by an i386 or x86_64 RPM that provides SASL-MYMECH
 and I definitely do not know the name of a file to put in the "Requires:"
header line.

Both uses cases arise from me wanting to place a dependency on some piece of
functionality but not a specific implementation of that piece of functionality.  

That leads me to two possible solutions: extend RPM so that I can specify an
architecture for a dependency (the subject of this bug) or have the packagers of
things like cyrus-sasl-md5 place a "Provides: xxx.%{_arch}" in their SPEC file?

Should I open bugs against cyrus-sasl-* and pam-* for this?  There's quite a few...

Curiously though:

$ rpm -q cyrus-sasl-md5
cyrus-sasl-md5-2.1.21-10.x86_64
cyrus-sasl-md5-2.1.21-10.i386

$ rpm -q --provides cyrus-sasl-md5
libcrammd5.so.2()(64bit)
libdigestmd5.so.2()(64bit)
cyrus-sasl-md5 = 2.1.21-10
libcrammd5.so.2
libdigestmd5.so.2
cyrus-sasl-md5 = 2.1.21-10

So RPM knows that the 64 bit and 32 bit versions are different, but,
frustratingly, I can't specify that I want one or the other in the .spec file.



Comment 5 Jeff Johnson 2006-09-07 11:49:05 UTC
The very simplest packaging solution is adding whatever digests
you want to your packaging. It's silly to add all the dependencies
and QA baggage if all you need is an MD5 (or SHA1) implementation,
there are numerous implementations available, even asm-coded,
that can be used instead. Its kinda pointless to do run-time loading
for well known algorithms.

But that's perhaps off topic ...

Comment 6 John Haxby 2006-09-07 11:56:56 UTC
It's not so much off-topic as misleading :-)  The cyrus-sasl RPMs are used for
SASL authentication, not for computing digests.  And bear in mind that this is
an example, albeit one that bit me.  Any RPM that wishes to express its
dependency on a plug-in is going to be bitten in the same way.

Comment 7 Jeff Johnson 2006-09-07 12:12:14 UTC
Not intentionally misleading.

rpm itself has exactly the same problem. gpg may implement
signing algorithms that are not supported within rpm (which
has its own crypto using beecrypt).

Internalizing the functionality is what I choose in rpm
because I can control the rpm but not the gpg implementations.

Granted SASL pretends to plug-in functionality, not just algorithm
functionality.

Generally, runtime (because dlopen is used) dependencies
on other packages that support (or don't) certain functionality must
be mapped into explicit provides of the necessary functionality, not
inferred from soname (or arch or version or whatever) contained
in the other package statically. That requires coordinaion between
the provider (cyrus-sasl) and the consumer (you) of the dependencies
that track the functionality.


Comment 8 John Haxby 2006-09-07 12:49:57 UTC
I understand, I think.  In this case, however, we have a two-level indirection.
 I have an automatically generated dependency on cyrus-sasl.i386 but since I
want to ensure that I can provide the CRAM-MD5 and DIGEST-MD5 authentication
mechanisms I have a functional dependency on cyrus-sasl-md5.i386.

I don't load /usr/lib/sasl2/libdigestmd5.so explicitly -- there is nothing at
all in my code that even hints at that as a possible file name.  All I do is ask
the cyrus-sasl library for a list of available SASL mechanisms.  Actually, if
cyrus-sasl-md5.i386 is missing, then my code still works and I can still do SASL
authentication, just not with CRAM-MD5 or DIGEST-MD5.  The dependency is purely
functional: the code doesn't behave the way it is supposed to for its clients
because the required authentication mechanisms aren't there.  (I have a similar
dependencies on certain compiled programs being present, but in that case I'm
not trying to dlopen them so I don't care what architecture they're compiled for.)

I think that you're suggesting that cyrus-sasl-md5.i386 should have a
"Provides:" header in its spec so that I can refer to that and yes, that would
work.  Of course, none of the cyrus-sasl-* or pam-* or j.random-plugin* packages
have such a header.  And the header needs to reflect the architecture on way or
another; the spec file needs to be able to say "I want to indirectly dlopen a
library that will provide xxx".  I don't much care if that's done by the spec
file cyrus-sasl-md5 (and all the rest) saying "Provides: sasl-md5.%{_arch}" or
"Provides: sasl-md5.32bit" or anything else, just so long as I can distinguish
it from the 64 bit version.

I guess what's really really at issue is that on a platform that supports two or
more different architectures (eg x86_65, ia64) then an executable that wants to
load a library at runtime needs to be able to express the fact that it needs the
right architecture library.  This is possible with the automatically generated
dependencies which are, of course, static, but is not possible with explicit
dependencies.

One way or another, I need to put "Requires: cyrus-sasl-md5.i386" in my spec
file -- in the case when I don't know the file name I have to other way to
express that dependency.  I don't much care whether this is done by
cyrus-sasl-md5 adding "Provides: cyrus-sasl-md5.%{_arch}" (and similarly for
_all_ other plug-ins that can be used in this way) or by extending the RPM
syntax to allow me to specify an architecture within a multilib system.

As I said, RPM already knows about multilibs and does its automatic (static)
dependencies knowing that, but it's frustrating that I can't do explicit
dependencies that way.

I suppose I could link libdigestmd5.so into some executable that's included in
the RPM package and get it that way, but apart from being an egregious hack,
that still requires me to know the pathname at the time I build the RPM.

So, to re-iterate:  I used to have:

   Requires: cyrus-sasl-md5

but that didn't work on a multilib system because cyrus-sasl-md5.x86_64 and
cyrus-sasl-md5.s390x (I think) satisfy the requirement but give 64 bit libraries
instead of 32 bit libraries.

What works at the moment is

   Requires: /usr/lib/sasl2/libdigestmd5.so

but that places an unwarranted build-time dependency on the packaging of
cyrus-sasl-md5 and there is no workaround for the postulated

   Requires: sasl-mymech

where I do not know the file name at build time.

And there are two possible solutions to this: the first is to extend RPM to
allow 32bit vs 64bit libraries to be expressed explicitly as well as implicitly
(via automatic dependencies).  The second is to modify all the possibly affected
RPMs (about a dozen, I think, for cyrus-sasl and PAM, not sure about other
plug-ins) to add a provides line that allows one to distinguish between the
32bit and 64bit variants.

I'll happily open bugs for any that I can think of if the latter is preferred,
but it really does seem to make more sense to allow the explicit expression of
that can be expressed implicitly.

Comment 9 Jeff Johnson 2006-09-12 21:36:31 UTC
You seem to be worried about including a path
    /usr/lib/sasl2/libdigestmd5.so
which might change someday. That's the only sense I can make
of "unwarranted".

I do poing out that dlopen'd modules are opened by path. While the
path might be configurable, or be runtime searched, a simple dlopen
implementation depends exactly on a path.

Another, path independent way, to require the dependency is to
use the internal soname

$ readelf -a /usr/lib/sasl2/libdigestmd5.so | grep SONAME
 0x0000000e (SONAME)                     Library soname: [libdigestmd5.so.2]

as (on elf32 platforms)
    Requires: libdigestmd5.so.2
and (on elf64 platforms except alpha)
    Requires: libdigestmd5.so.2()(64bit)
although I'm not sure what has been gained since dlopen() access
is by path, not by DT_SONAME, with different paths on elf32/elf64 systems.

No matter what, a dependency on a package name will not "work" with multilib.

Its kinda pointless imho to worry about hypothetical situations like sasl-mymech.

I return to my original general observation, that packages for one arch should
not need to depend on packages for other arches, and have given you several
examples of how you package problem can be solved without adding a means
to explicitly specify an arch in a dependency. We disagree.

Comment 10 Matthew Miller 2007-04-06 17:31:22 UTC
Fedora Core 5 and Fedora Core 6 are, as we're sure you've noticed, no longer
test releases. We're cleaning up the bug database and making sure important bug
reports filed against these test releases don't get lost. It would be helpful if
you could test this issue with a released version of Fedora or with the latest
development / test release. Thanks for your help and for your patience.

[This is a bulk message for all open FC5/FC6 test release bugs. I'm adding
myself to the CC list for each bug, so I'll see any comments you make after this
and do my best to make sure every issue gets proper attention.]


Comment 11 Jeff Johnson 2007-04-11 12:11:58 UTC
Please add comments to

    https://lists.dulug.duke.edu/pipermail/rpm-devel/2007-April/002260.html

Comment 12 Panu Matilainen 2007-08-07 11:22:57 UTC

*** This bug has been marked as a duplicate of 235755 ***


Note You need to log in before you can comment on or make changes to this bug.