Protected visibility for glib



Hi all,

I did a little bit more poking around after my last mail to the list on
the topic of alternatives to galias.  I've come up with what I believe
to be a workable solution.

My approach can be summarised as such:

  - remove all previous galias stuff

  - replace G_BEGIN_DECLS/G_END_DECLS with "protected" visibility
    pragmas.  This means that any symbol declared in a header file
    will end up with protected visibility.

  - deal with the take-address-of-protected-symbol problem with a pair
    of macros.  G_INTERNAL_FUNC() must be used anywhere when taking the
    address of a glib function from inside of glib (ie: when creating a
    hash table with g_str_hash(), for example). 
    G_DEFINE_INTERNAL_FUNC() must be used at the site of the definition
    of any public function that might also have its address taken from
    inside of glib.  There are 8 of these:

      g_free, g_option_group_free, g_scanner_error, g_scanner_warn,
      g_str_equal, g_str_hash, g_direct_hash.

    and about 30 places where G_INTERNAL_FUNC() needs to be used.


    These macros work by creating a (familiar) IA__funcname alias for
    the symbol that is declared with hidden visibility instead of
    protected and using that symbol in place of the protected one.


See the 'protected-visibility' branch that I just pushed to the glib
repository.  I've only made changes to the glib/ directory -- not
gobject/ or gio/ (although those could easily use the same technique).

I'll list what I consider to be the pros and cons of this approach here:

Benefits:

  - It becomes possible to have macros and functions with the same
    name.  Behdad recently ran into trouble with this with a feature he
    wanted to add to g_malloc_n.  I also recently wanted to use this
    ability for some better type safety on a couple of functions.

  - No PLT entries.  The galias solution had some situations it couldn't
    deal with (mostly because of inline functions), so we had a list of
    exceptions in the pltcheck.sh.  With the new system there are no
    exceptions.

  - The libglib-2.0.so file becomes slightly smaller (about 3.5%). I
    think that this is mostly because of not having two copies of every
    symbol (the func and IA__func versions).

  - The build gets faster.  I've measured a drop from 34 seconds for
    glib/ (and tests) to 27 seconds on my laptop.  Probably due to not
    having to chew through galias.h and galiasdef.c for every file.

  - (the big benefit for me) No need to rebuild the entire source tree
    when adding a new symbol (due to galias.h and galiasdef.c changing).

  - Removes the cruft with #define __FILE_C__ and #include "galiasdef.c"
    from the end of each file.

Drawbacks:

  - The G_INTERNAL_FUNC() macro is ugly.  That's too bad.  The 8
    instances of G_DEFINE_INTERNAL_FUNC() are a little bit ugly too, but
    certainly much less ugly than #include "galiasdef.c" in every file.

  - We still have the problem that we had with galias that we can't
    compare function pointers.  I don't know of anyone who has ever
    wanted to do this, but it could be the source of confusing bugs in
    the future.  The benefit is that with the G_INTERNAL_FUNC() macro it
    should be more obvious that magic is going on here.

  - Doesn't have the tried-and-tested benefit that galias has.

  - Makes it easier for people not to update the symbols file properly. 
    I've left the ABI check enabled, though, so you'll hear about the
    problem as soon as you run 'make check'.


I think that we should do this in the next cycle of glib.

I'd appreciate it if people could look at what I've done and try to find
problems with it.

Cheers



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