Subject: Re: Making DLL's.
From: Fergus Henderson <[email-masked]>
To: "Gary V. Vaughan" <[email-masked]>
Cc: [email-masked]
Date: Tue, 23 Mar 1999 09:50:31 +1100

On 22-Mar-1999, Gary V. Vaughan <[email-masked]> wrote:
> The only fly in the ointment for libtool's dll support is handling the export
> of data items from a dll.  Specifically, an object that will be linked into
> an executable which will in turn be linked with a handful of libraries (some
> static and some dll's, for argument's sake) needs to produce different code
> depending on what particular combinations of dll and static libraries it will
> ultimately be linked with.
> 
> That is I need to make sure that any data item that will be imported from a
> dll has __attribute__((dllimport)), and any data item imported from a static
> library cannot have this attribute.  Obviously, in a makefile driven build
> environment there is no easy way to know which combination of libraries this
> object will eventually be linked with... is there a way around this problem?
> Or do I have to come up with some kind of makefile scanner to figure out
> which attributes to attach to each symbol?
>
> Actually, libtool compounds the problem, because it wants to produce both
> static and dll libraries for each library object, and thus a given data symbol
> may be:
>         1) exported from this object if the object will be part of a dll
>         4) externed in the tradition way if it will be part of a static lib

The difference between 1) and 4) is already important on many Unix
systems, where you need to compile with `-fpic' in case 1),
but you don't need any special options in case 4).
So your Makefile ought to already be set up to handle this.
On Windows, just replace `-fpic' with `-DCOMPILING_FOO_DLL'
and then use the #ifdefs you mentioned.

(N.B. You should really use `COMPILING_FOO_DLL' rather than
`_COMPILING_FOO_DLL_', because according to ISO C and C++,
the latter is reserved for use by the implementation.)

>         2) imported from another dll
>         3) imported from a static library

This distinction is not present in Unix, and yes, it is
a real pain.  I have avoided it by either always using
a static library or always using a DLL for any given 
library.

> So, my question is:  do I really have to figure out whether this object is
> destined to become part of a static library, a dll, or an executable, and
> which libraries that destination will depend on and whether each of them will
> be a dll or not in order to produce the correct code for each exported data
> symbol?

Basically yes.  And it is a real pain.
But it's not _quite_ as bad as you make out.

> My (flawed) best solution so far is:
> 
>         /* foo.h */
>         #ifdef __CYGWIN__
>         #  ifdef _COMPILING_FOO_DLL_
>         #    define EXTERN __declspec(dllexport)
>         #  else
>         #    define EXTERN extern __declspec(dllimport)
>         #  endif
>         #else
>         #  define EXTERN extern
>         #endif
> 
>         EXTERN int foo;

A potentially better alternative is

         /* foo.h */
         #if defined(__CYGWIN__) && defined(DEFINE_FOO_DLL)
         #  define FOO_EXTERN __declspec(dllexport)
         #elif defined(__CYGWIN__) && defined(USE_FOO_DLL)
         #  define FOO_EXTERN extern __declspec(dllimport)
         #else
         #  define FOO_EXTERN extern
         #endif
 
         FOO_EXTERN int foo;

(I prefer the name DEFINE_FOO_DLL rather than COMPILING_FOO_DLL.)

Note that if you're using C rather than C++, then it is in fact
possible to simplify this a little, so that you don't need to add all
those FOO_EXTERN symbols to all the declarations in the header files. 
See <http://www.cs.mu.oz.au/~fjh/gnu-win32/how-to-build-dlls.html> for
details.  Note that the stuff there is fairly old; it dates back to
version b18 or thereabouts.  I haven't tested it with more recent versions.

> When building the dll, I need:
> 
>         /* foo.c */
>         #define _COMPILING_FOO_DLL_
>         #include "foo.h"
...
> Which works fine, until I try to build an equivalent static libfoo.a from the
> foo sources on cygwin, when ofcourse I get `undefined __imp_foo' errors =(O|

It's better to pass -D_COMPILING_FOO_DLL_ or -DDEFINE_FOO_DLL
on the command line via make, rather than hard-coding it
in your source file.  That way you can avoid passing it when you
build your static libraries.

-- 
Fergus Henderson <[email-masked]>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger [email-masked]        |     -- the last words of T. S. Garp.

--
Want to unsubscribe from this list?
Send a message to [email-masked]