On Thu, 2007-12-20 at 00:51 -0800, Steve Langasek wrote: > On Mon, Dec 10, 2007 at 09:47:36PM +0100, Simon Richter wrote: > > >>> No, what can be done is to fix upstream's broken declaration that 'you can > >>> assume glib functions are available when doing "#include <gtk/gtk.h>"'. It > >>> doesn't follow that just because this works in practice, it should be a > >>> supported usage. > > >> When many of the types used by GTK+ are those provided by GLib, it > >> sounds wrong to ask developers to include the GLib headers to have these > >> types available. > > > If it is really expected that type declarations are to be shared between a > > program and a library, then the program becomes dependent on the library's > > ABI without this dependency being formally expressed in any usable form, > > which is broken in and by itself. > > > GTK needs to provide its own definitions of types and not expose interfaces > > it does not control. > > Fine in theory, in practice this can be a significant burden to the library > maintainer. FWIW, I don't see any reason why a library can't use > externally-defined types directly, /as long as/ they have some mechanism for > ensuring ABI consistency between the two libraries (i.e., an ABI change in > the underlying library is always accompanied by an soname change in the > dependent library). I'd make a stronger statement and say that reusing types is a positive thing. If you are reusing a glib list in your pet library, creating your own type makes your library incompatible with other libraries also using glib lists and providing code to manipulate them... and if it doesn't make it incompatible then its not going to achieve the ABI considerations that are under discussion here. So really I think each dependant library of a library that is dynamically linked to falls into one of two categories: - internal detail - implementation detail resulting in exposed ABI So if I link program X against libfoo which uses libbar, if libbar is an internal detail of libfoo then: libfoo -> libbar@some ABI X -> libfoo@libfoo's ABI only. And a rebuild of libfoo to link a new libbar ABI won't break X, nor will it require a rebuild of X. The conditions for internal detail only are very stringent: compiler alignment, structure sizes etc etc for all non opaque (where opaque is opaque to the /compiler/ not to the user's code!) exported types of libfoo must not be dependent on libbar at all. I doubt that many libraries will meet this requirement for all their dependent libraries (and consider libc as just an extremely common case of this). For all other cases, when a used ABI gets exposed, while we may not want X to depend (at the package level) on libbar; at an ABI level it does. We need to decide how we represent that. We also have at least two dimensions here: runtime linker behaviour package management behaviour From the runtime linker we want: * an error/warning/something when two instances of the same API with different ABI's are loaded. This commonly occurs when libbar.1 and libbar.2 are both loaded, but it can occur more generally when libbar is renamed to libquux and then libbar.1 and libquux.2 are loaded (by X and libfoo respectively). * To be able to interrogate how something was linked sufficiently well to generate packaging metadata automatically. From the package manager we want: * To know when we have to rebuild X because libbar has changed. * To allow upgrades to libbar on users systems without changing X when possible. The case where libbar is an internal detail is trivial (detection isn't: see abicheck and icheck - libraries really need icheck in the package build rules IMNSHO); I'm going to ignore it here. For the case where libbar is not an internal detail. Starting with packaging as thats easiest: * we should depend on a minimum version of the libbar we need (as we already bump the package name when the ABI changes incompatibly in a library this is straight forward) and gives the opportunity to upgrade libbar within an ABI safely. * we can do an rdepends on e.g. libbar2 when libbar's API changes from 2 to 3 to find packages we need to rebuild. One defect here is when symbols are shared from within a non-library - e.g. the case with some programs plugin's. Here, a plugin may use a symbol from within the program X, which is ABI dependent all the way back, so treating programs as libraries - that is having an ABI - might make sense. I haven't considered this in detail... The runtime loader is more tricky: * If we link X to libfoo only: - libfoo's soname has to be manually changed when libbar's changes or hilarity results - we don't have a robust way that I know of to interrogate X to find out that we need a package dependency on libbar + we don't need to have libbar present when it is only optionally used (that is by calling some libfoo feature that needs libbar) * If we link X to libbar directly: - because we can't tell how much of recent changes to libbar are needed, any installation of a build of X will force an upgrade of libbar to the version it was built against, unless a bunch of extra effort is put in. + we can determine that X has a dependency on libbar specifically - we always require libbar to be present (IIRC) I don't think we have a good answer to this in general, and I think we need to do some infrastructure work to be able to have one. > (BTW, pkg-config upstream wrongly claims that exporting dependent libs > in the pkg-config --libs output provides this protection. :/) It doesn't? (I must be missing something as I thought it did, just over aggressively). -Rob -- GPG key available at: <http://www.robertcollins.net/keys.txt>.
Description: This is a digitally signed message part