[Help-gnutls] Re: duplicate symbols complaint on Mac OS X 10.5.2

Simon Josefsson simon at josefsson.org
Thu Mar 20 15:32:05 CET 2008

ludo at gnu.org (Ludovic Courtès) writes:

> Hi,
> Simon Josefsson <simon at josefsson.org> writes:
>> Anyway, I don't see any harm in setting the compiler in C99 mode if the
>> compiler supports it.
> One possible problem is that you end up writing C99 code, using
> C99-specific things like, say, C++-style comments, declarations not at
> the beginning of a block, etc.  These things will break with non-C99
> compilers.

Yes, but anything like that would be bugs.  We still target C89 + POSIX
sockets.  Gcc's default mode is gnu89 (I think?), which does permit some
things from C99, so we have had this problem forever.

I used to build gnutls on solaris, aix, hpux etc for every release using
their native compilers, but I don't have the resources to do it any
more.  If someone have access to these platforms and want to setup an
autobuilder, we would catch any regression soon (btw, see

>> If the compiler doesn't supports those, we'll disable those features or
>> use our gnulib-workarounds, which seems sub-optimal.  We want our code
>> to work with C99.
> To "work with C99" or to "require C99"?  Surely either is acceptable,
> but I have the impression that there's a slow movement towards the
> latter.

Unfortunately, I think it is too early to require C99.  A lot of
embedded and less capable systems need gnutls, and they barely have C89
support even these days.

>> I still don't see how this problem occur though.  Exactly how is the
>> gmpz_abs symbol pulled into guile/src/*.o files?  If gmpz_abs is inline
>> in gmp.h, should that be inlined into the guile code?  Does setting the
>> compiler in gnu99 mode also set the linker in a different mode, that
>> causes this problem?
> <libguile.h> includes <libguile/numbers.h>, which in turn includes
> <gmp.h>, which contains declarations and "extern inline" definitions (in
> the "GNU89" sense).

Ah, that helps.

> Why it `__gmpz_abs' ends up as a global, exported symbol in the `.o'
> objects produced on MacOS X, I have now idea.

As far as I can tell, it would only happen if some code in gnutls uses
some guile declaration that implicitly calls gmpz_abs.  However, I
couldn't find any: the only libguile header that mention gmp types or
functions is numbers.h:

jas at mocca:~$ grep -i mpz /usr/include/libguile/*
/usr/include/libguile/numbers.h:/* Each bignum is just an mpz_t stored in a double cell starting at word 1. */
/usr/include/libguile/numbers.h:#define SCM_I_BIG_MPZ(x) (*((mpz_t *) (SCM_CELL_OBJECT_LOC((x),1))))
/usr/include/libguile/numbers.h:SCM_API void scm_to_mpz (SCM x, mpz_t rop);
/usr/include/libguile/numbers.h:SCM_API SCM  scm_from_mpz (mpz_t rop);
jas at mocca:~$ 

I don't see how mpz_abs is called here though.

> On GNU/Linux with GCC 4.2.3, it never happens, whether compiled with
> `-std=c99' or not.

'extern inline' means, I think, that stand-alone object code is still
generated and can be used by external code.  So any code that use calls
mpz_abs would declare an external symbol as well.  However, it seems to
me that this should only be a weak symbol, so I don't understand how
there could be a symbol collision.

Hm.  There is actually some interesting discussion in gmp.h:

/* The following are provided as inlines where possible, but always exist as
   library functions too, for binary compatibility.

   Within gmp itself this inlining generally isn't relied on, since it
   doesn't get done for all compilers, whereas if something is worth
   inlining then it's worth arranging always.

   There are two styles of inlining here.  When the same bit of code is
   wanted for the inline as for the library version, then __GMP_FORCE_foo
   arranges for that code to be emitted and the __GMP_EXTERN_INLINE
   directive suppressed, eg. mpz_fits_uint_p.  When a different bit of code
   is wanted for the inline than for the library version, then
   __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs.  */

#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_abs)
mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u)
  if (__gmp_w != __gmp_u)
    mpz_set (__gmp_w, __gmp_u);
  __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size);


More information about the Gnutls-help mailing list