Configure, DLL_EXPORT, and why --enable-shared fails on Cygwin

librik@panix.com librik at panix.com
Tue Apr 4 04:33:14 CEST 2006


GMP 4.2 will not build as a shared library (DLL) under Cygwin,
except in a generic C (no assembly language) version.

I think I have worked out the reason for this, but I'm not
sure what to do about it, so I'll have to describe the problem
and appeal to more experienced build-system developers for help.

In short, the problem seems to be that the preprocessor define
DLL_EXPORT is no longer passed to GCC by libtool.  But the
mpn/x86/x86-defs.m4 file, used to build x86 assembly language
code, relies on DLL_EXPORT to tell Windows from Linux.

More detailed analysis follows:


When you try to construct a GMP DLL in Cygwin, using
    > ./configure --enable-shared --disable-static
    > make
the Cygwin GNU assembler (as) dies with an assert failure on
mpn/x86/dive_1.asm.
     gcc -c -DHAVE_CONFIG_H -I. -I. -I.. -D__GMP_WITHIN_GMP -I..
       -DOPERATION_dive_1 -m32 -O2 -fomit-frame-pointer -mtune=pentium4
       -march=pentium4 tmp-dive_1.s -DPIC -o .libs/dive_1.o
     /usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/bin/as:
       BFD 2.16.91 20050610 assertion fail /netrel/src/binutils-20050610-1/
       bfd/coff-i386.c:576
     tmp-dive_1.s: Assembler messages:
     tmp-dive_1.s:121: Error: cannot represent relocation type
        BFD_RELOC_386_GOTPC

That assertion is BFD's way of saying that it cannot handle
the constant $_GLOBAL_OFFSET_TABLE that's in the dive_1.asm
sources.  But the G.O.T. shouldn't be in Windows code; it's
only meaningful in ELF binaries.  And it never caused trouble
when it was used in GMP 4.1.4.  What's going on?

The answer is that the code containing $_GLOBAL_OFFSET_TABLE
is inside "ifdef(`PIC`)" in dive_1.asm, and that ifdef block
should have been removed by this m4 macro in mpn/x86/x86-defs.m4:

  dnl  Libtool gives -DPIC -DDLL_EXPORT to indicate a cygwin or mingw DLL.  We
  dnl  undefine PIC since we don't need to be position independent in this
  dnl  case and definitely don't want the ELF style _GLOBAL_OFFSET_TABLE_ etc.

  ifdef(`DLL_EXPORT',`undefine(`PIC')')

What's changed between GMP 4.1.4 and GMP 4.2 is the macro
DLL_EXPORT.  It no longer appears in the command line
constructed by configure in libtool when you're building
a DLL in Cygwin.  But x86-defs.m4 is still relying on it.


So I can see two possibilities:

(1) x86-defs.m4 should be using some other macro to
detect a Cygwin DLL build.  (But I don't see anything
else useful in the gcc command line, above.)

(2) It was a mistake to remove -DDLL_EXPORT from the
command line constructed in libtool by configure.


It's worth noting that in GMP 4.1.4, configure has several
sections like this:
    cygwin* | mingw* | pw32* | os2*)
      # This hack is so that the source file can tell whether it is being
      # built for inclusion in a dll (and should export symbols for example).
      lt_prog_compiler_pic='-DDLL_EXPORT'
but in GMP 4.2 these sections are missing "cygwin*":
    mingw* | pw32* | os2*)
      ....
When I restore "cygwin*" to the case statements (which
sometimes requires removing it from nearby case statements),
the GMP 4.2 DLL with assembler modules successfully builds!


So I would argue that restoring it is the correct move; i.e.,
(2) it was a mistake to remove -DDLL_EXPORT for Cygwin in the
first place.

I don't know if this is a GMP problem, or one related to autoconf,
automake, and libtool.  The documentation for the latter triad
(the Goat Book) is so far out of date that it's useless in this
situation.

Can the developers for the GMP 4.2 build system suggest what the
right solution should be?


- David Librik
librik at panix.com



More information about the gmp-devel mailing list