[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Shared libs dependencies



Not using symbols files will give you almost always too strict dependencies,
usually forcing users to also upgrade libraries without need, but
everything dpkg will not complain about will work (assuming a sane
upstream not breaking ABI without changing sonames).

Using symbols files means the dependencies are less tight, one gets some
basic checks against upstream failing to keep ABI, but the burden is on
the maintainer to know when the ABI changed backward-compatible but not
forward-compatible in existing symbols.

* Sven Joachim <svenjoac@gmx.de> [110924 10:43]:
> Erm, this will also happen if you don't have symbols files.  In fact,
> using symbols files together with "dpkg-gensymbols -c4" catches this
> kind of mistake.

The real problem with using symbol files without understandin them is
something like the following examples:

--- example 1 ----

liba 1.0.0:

        /usr/include/a.h:

        enum command {
                command_start,
                command_stop
        };
        extern void do(enum command);

liba 1.1.0:

        /usr/include/a.h:

        enum command {
                command_start,
                command_stop,
                command_restart
        };
        extern void do(enum command);

someprog:

        checking for command_restart in configure and then in the source

        #ifdef HAVE_COMMAND_RESTART
        do(command_restart);
        #else
        do(command_stop);
        do(command_start);
        #endif

There is no symbol changed in liba, so the symbols file for liba 1.1.0
will still say 1.0.0 for do. But if you compile someprog with the newer
liba, it will give "2" to do, which the older liba does not understand,
so the symbols file is incorrect.

--- example 2 ----

I think I've already seen a scheme like the following somewhere:

libb 1.0.0:

        /usr/include/b.h:

        struct data {
                size_t size;
                void *value;
        };

        #define init_data(d) ({ d.size = sizeof(d); d.value = NULL; })
        void do(struct data *);

libb 1.1.0:

        /usr/include/b.h:

        struct data {
                size_t size;
                void *value;
                bool reverse;
        };

        #define init_data(d) ({ d.size = sizeof(d); d.value = NULL; d.reverse = false })
        void do(struct data *);

A scheme like this (the #define is only here to show how it is used,
that might also be part of documentation) is a nice way to support
adding fields without breaking the ABI: a program compiled against the
old value gives the old size, the new library can cope with that and
does not need to change the soname. But of course if something is
compiled with the new version, it gives a value the old version cannot
handle.
But again dpkg-symbols can see no difference, so if just applying the
patches dpkg-symbols generates means the symbols file will still think
libb 1.0.0 is enough when only calling "do".



	Bernhard R. Link


Reply to: