L. The second define is
'-DLIBFOO_BUILD' (or similar), which is often added by the package
providing the library and is used when building the library, but not
when consuming the library.

   However, the matching double compile is not performed when consuming
libraries.  It is therefore not possible to reliably distinguish if the
consumer is importing from a DLL or if it is going to use a static
library.

   With contemporary GNU tools, auto-import often saves the day, but see
the GNU ld documentation and its '--enable-auto-import' option for some
corner cases when it does not (*note '--enable-auto-import':
(ld)Options.).

   With Microsoft tools you typically get away with always compiling the
code such that variables are expected to be imported from a DLL and
functions are expected to be found in a static library.  The tools will
then automatically import the function from a DLL if that is where they
are found.  If the variables are not imported from a DLL as expected,
but are found in a static library that is otherwise pulled in by some
function, the linker will issue a warning (LNK4217) that a locally
defined symbol is imported, but it still works.  In other words, this
scheme will not work to only consume variables from a library.  There is
also a price connected to this liberal use of imports in that an extra
indirection is introduced when you are consuming the static version of
the library.  That extra indirection is unavoidable when the DLL is
consumed, but it is not needed when consuming the static library.

   For older GNU tools and other proprietary tools there is no generic
way to make it possible to consume either of the DLL or the static
library without user intervention, the tools need to be told what is
intended.  One common assumption is that if a DLL is being built
('DLL_EXPORT' is defined) then that DLL is going to consume any
dependent libraries as DLLs.  If that assumption is made everywhere, it
is possible to select how an end-user application is consuming libraries
by adding a single flag '-DDLL_EXPORT' when a DLL build is required.
This is of course an all or nothing deal, either everything as DLLs or
everything as static libraries.

   To sum up the above, the header file of the foo library needs to be
changed into something like this:

   Modified 'foo.h':

     #ifndef FOO_H
     #define FOO_H

     #if defined _WIN32 && !defined __GNUC__
     # ifdef LIBFOO_BUILD
     #  ifdef DLL_EXPORT
     #   define LIBFOO_SCOPE            __declspec (dllexport)
     #   define LIBFOO_SCOPE_VAR extern __declspec (dllexport)
     #  endif
     # elif defined _MSC_VER
     #  define LIBFOO_SCOPE
     #  define LIBFOO_SCOPE_VAR  extern __declspec (dllimport)
     # elif defined DLL_EXPORT
     #  define LIBFOO_SCOPE             __declspec (dllimport)
     #  define LIBFOO_SCOPE_VAR  extern __declspec (dllimport)
     # endif
     #endif
     #ifndef LIBFOO_SCOPE
     # define LIBFOO_SCOPE
     # define LIBFOO_SCOPE_VAR extern
     #endif

     LIBFOO_SCOPE     int one (void);
     LIBFOO_SCOPE     int two (void);
     LIBFOO_SCOPE_VAR int three;

     #endif /* FOO_H */

   When the targets are limited to contemporary GNU tools and Microsoft
tools, the above can be simplified to the following:

   Simplified 'foo.h':

     #ifndef FOO_H
     #define FOO_H

     #if defined _WIN32 && !defined __GNUC__ && !defined LIBFOO_BUILD
     # define LIBFOO_SCOPE_VAR extern __declspec (dllimport)
     #else
     # define LIBFOO_SCOPE_VAR extern
     #endif

     int one (void);
     int two (void);
     LIBFOO_SCOPE_VAR int three;

     #endif /* FOO_H */

   This last simplified version can of course only work when Libtool is
used to build the DLL, as no symbols would be exported otherwise (i.e.,
when using Microsoft tools).

   It should be noted that there are various projects that attempt to
relax these requirements by various low level tricks, but they are not
discussed here.  Examples are FlexDLL
(http://alain.frisch.fr/flexdll.html) and edll
(http://edll.sourceforge.net/).

