[csw-maintainers] Shared library placement proposal

Jonathan Craig jcraig at opencsw.org
Wed Feb 16 16:14:27 CET 2011


2011/2/16 Maciej Bliziński <maciej at opencsw.org>:

>> We can certainly discuss it but do we wish to hold up progress on
>> library placement for a sidebar discussion on how to support multiple
>> versions of a given runtime library for developers?  One of the goals
>> was to decouple the shared library issue from how to support multiple
>> versions of a given application and then the proposal drives right
>> into this issue.
>
> True, although the proposal only deals with shared libraries.  In most
> cases, supporting multiple versions is about conflicting executable
> names, e.g. in mysql or postgresql.  We could take this issue out of
> the proposal, but it seems to me like the two issues are so closely
> related, they are best covered by a single document.
>

I'm okay with discussing and if time pressures demand we can sever the
issue into its own space.

> There are two options: using a separate prefix, and using subdirectories.

Actually they amount to the same thing, they only differ in approach.
One creates a bundled custom prefix (lib,bin,include together) and the
other creates an unbundled custom prefix (lib, bin, include could be
anywhere).  The biggest difference would be an application that only
allows you to specify a base directory for a library rather than allow
explicit naming of each component.  For these applications the
maintainer would need to explicitly add -L/-I flags to allow the
configure script to find these libraries.  (argument for/against
bundled vs unbundled custom prefix).

> The --prefix way (used with berkeleydb):
>

This is what I would call the "bundled" custom prefix.

> CSWlibfoo1
> /opt/csw/libfoo1/lib/libfoo.so.1
> CSWlibfoo1_dev
> /opt/csw/libfoo1/include/foo.h
> /opt/csw/libfoo1/lib/libfoo.so -> libfoo.so.1
>
> CSWlibfoo2
> /opt/csw/libfoo1/lib/libfoo.so.2
> CSWlibfoo2_dev
> /opt/csw/libfoo2/include/foo.h
> /opt/csw/libfoo2/lib/libfoo.so -> libfoo.so.2
>
> In this scenario, you always have to specify
> -I/opt/csw/libfoo1/include or -I/opt/csw/libfoo2/include, and
> -L/opt/csw/libfoo1/lib or -L/opt/csw/libfoo2/lib, otherwise the
> software you're compiling will not be able to find libfoo.  Even if
> you want to link against the newest version (the default), you still
> have to specify these options.
>
> If you bring 64-bit libraries into the picture, the layout needs to
> include the 32 and 64 links:
>
> CSWlibfoo1
> /opt/csw/libfoo1/lib/libfoo.so.1
> /opt/csw/libfoo1/lib/sparcv9/libfoo.so.1
> /opt/csw/libfoo1/32 -> .
> /opt/csw/libfoo1/64 -> sparcv9
> CSWlibfoo1_dev
> /opt/csw/libfoo1/include/foo.h
> /opt/csw/libfoo1/lib/libfoo.so -> libfoo.so.1
> /opt/csw/libfoo1/lib/sparcv9/libfoo.so -> libfoo.so.1
>
> CSWlibfoo2
> /opt/csw/libfoo2/lib/libfoo.so.2
> /opt/csw/libfoo2/lib/sparcv9/libfoo.so.2
> /opt/csw/libfoo2/32 -> .
> /opt/csw/libfoo2/64 -> sparcv9
> CSWlibfoo2_dev
> /opt/csw/libfoo2/include/foo.h
> /opt/csw/libfoo2/lib/libfoo.so -> libfoo.so.2
> /opt/csw/libfoo2/lib/sparcv9/libfoo.so -> libfoo.so.2
>
>
> The second option, using subdirectories (and 64-bit libs):

What I would call the "unbundled" custom prefix.

>
> CSWlibfoo1
> /opt/csw/lib/libfoo.so.1
> /opt/csw/lib/sparcv9/libfoo.so.1
> CSWlibfoo1_dev
> /opt/csw/include/libfoo1/foo.h
> /opt/csw/lib/libfoo1/libfoo.so -> ../libfoo.so.1
> /opt/csw/lib/libfoo1/sparcv9/libfoo.so -> ../../sparcv9/libfoo.so.1
>
> CSWlibfoo2
> /opt/csw/lib/libfoo.so.2
> /opt/csw/lib/sparcv9/libfoo.so.2
> CSWlibfoo_dev
> /opt/csw/include/foo.h
> /opt/csw/lib/libfoo.so -> libfoo.so.2
> /opt/csw/lib/sparcv9/libfoo.so -> libfoo.so.2
>
> In this scenario, you can pass the standard flags (-I/opt/csw/include
> and -L/opt/csw/lib) and your software will link to the newest version
> of libfoo.  If an older version is necessary, you need to pass
> additional -I and -L.
>

One detractor to this approach is the need to update the old package
to allow the new package or you have a file conflict for the
/opt/csw/lib/libfoo.so -> xxx link.  I suppose this could be left to a
post install script but then you have a last package wins scenario.
This makes the build state non-deterministic which can be problematic
for troubleshooting.

>>>> and I would prefer a method more like the
>>>> one used by ubuntu.  This places the include.h and the libfoo.so link
>>>> into a versioned package like libfoo2.0-dev.  This allows the end-user
>>>> to choose the default development version of the library to use with
>>>> builds by choosing the approriate -dev package.  The libfoo-rt package
>>>> then would only have the libfoo.so.1 file needed by executables.
>>>>

>>>> Now libfoo1rt and libfoo2rt can coexist and the end-user can choose
>>>> which library they want to develop against by choosing the appropriate
>>>> -dev package.
>>>
>>> In our case it can't be done by including files directly in packages.
>>> If you tried to release the -dev packages like this, your second
>>> package would be rejected with a note that it conflicts with the first
>>> one.  Perhaps an approach using alternatives could be used: place
>>> files elsewhere and provide symlinks.
>>
>> Cant be done given the existing implementation or cant be done at all.
>>  Should we limit our solutions to the existing code if it precludes
>> the implementation of a more elegant solution?
>
> In short, can't be done at all, unfortunately.
>
> The issue of conflicting files stems from the workings of Solaris
> packages.  In dpkg for example, it is not allowed for one file to be
> owned by two packages.  IIRC, you can create two packages providing
> the same file, but dpkg will not allow you to install them.  In
> Solaris, pkgadd will return a success exit code and will overwrite the
> existing file on disk.  In this scenario, whichever package was last,
> wins.  This is not acceptable, so we need to enforce file uniqueness
> by never creating packages with conflicting files.
>

This is where ubuntu uses a "conflicts with" dependency and only
allows one development option to be installed at a time thereby
sidestepping the issue of file conflict.  Could we not also create a
"conflicts with" dependency?

> The issue surfaced not so long ago, so there still is a good deal of
> conflicting files in the catalog[1].
>
> If we encounter a case of colliding files, we need to either rename
> one or both files, or use alternatives.
>

Seems like an argument for having a "conflicts with" dependency.

>>> There's one issue to be addressed: we are using shared build systems
>>> on the buildfarm (e.g. current9s).  It needs to be possible to link to
>>> libfoo.so.2 as well as libfoo.so.1 on a single system, without any
>>> global package manipulation (and root / sudo access).
>>
>> Hmm, this is a tough one because its a situation we have as a
>> maintainer community that isn't as much of an issue for an end user.
>> An end user can install/re-install the -dev package as needed.  Access
>> to the shared library could be handled by creating a "lib" directory
>> in the package build space that creates the symlink to whatever
>> version of the shared library.  This doesn't solve the issue of
>> conflicting include files.  For the build farm could we have
>> installation of development packages into private root directories
>> that are added to the using -L/-I options but expect to find their
>> runtime libraries in /opt/csw/lib using -R.
>
> It would mean that we release development packages that we don't use
> ourselves.  We would need to have an additional testing environment.
> That's a relatively large amount of work, where the group benefiting
> from it is probably very small, since we rarely hear from people
> building software using packages; and when we do, they usually become
> maintainers.
>

No, what I was thinking of was specifying and "alternate_root" (pkgadd
-R) when installing the development packages that would allow the
maintainer to bypass the issue of file conflict. This is only intended
to resolve the issue that we face in the build farm.  So if we choose
an alternate root base directory like /csw_dev/ then libfoo1-dev could
be installed in /csw_dev/libfoo1-dev.  Libraries are then available as
 /csw_dev/libfoo1-dev/opt/csw/lib/libfoo.so.  The maintainer then
specifies these directories in their -I/-L arguments.  We would then
be using the same packages as end-users, just installed into an
alternate path.

> Going back to the library placement proposal - if the linking against
> old libraries section is going to grow more, it should be taken out to
> a separate document.  The proposal can simply mention that it does not
> prevent older shared libraries from being linked to.
>
> What do you think?
>

Its a chicken and egg situation.  Saying that shared libraries must be
available in the global /opt/csw/lib directory means that all of these
other things will need to be answered.  Choices have impact, but that
shouldn't turn us from facing them.  I personally don't look at
policies as being written in stone and therefore require exhaustive
research to fully specify them the first time.  Policy simply directs
our actions in achieving a given outcome.  As our understanding of the
desired outcome develops, so must our policy.  Lets capture our
perception of what the desired outcome is and then we can kraft the
policies over time to see they are achieved.


More information about the maintainers mailing list