libtool-patches
[Top][All Lists]
Advanced

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

Re: [RFC] w32 and Libtool.


From: Ralf Wildenhues
Subject: Re: [RFC] w32 and Libtool.
Date: Sat, 30 Oct 2010 09:15:04 +0200
User-agent: Mutt/1.5.20 (2010-08-04)

[ dropping libtool@ ]

Hi Peter,

* Peter Rosin wrote on Fri, Oct 29, 2010 at 10:00:34PM CEST:
> This time as a patch.  Ok to push, or did I screw up the texification?

Good with minor nits, but allow a day or so for comments from others.
Thanks!

Cheers,
Ralf

> Subject: [PATCH] docs: Windows DLLs and headers.
> 
> * doc/libtool.texi (Platform quirks): Add new subsection
> 'Windows DLLs'.

> --- a/doc/libtool.texi
> +++ b/doc/libtool.texi

> @@ -6321,6 +6323,194 @@ the source or build directory trees, and all 
> @option{-M*} options to
>  This is quite a fragile setup, but it has been in historical use, and so is
>  documented here.
>  
> address@hidden Windows DLLs
> address@hidden Windows DLLs
> address@hidden Windows DLLs
> +
> +This topic describes a couple of ways to portably create Windows Dynamic
> +Link Libraries (DLLs).  Libtool knows how to create DLLs using GNU tools
> +and using Microsoft tools.
> +
> +A typical library has a "hidden" implementation with an interface

Double quotes render ugly in PDF except in code bits, prefer ``hidden''
if you need to use quoting.

> +described in a header file.  On just about every system, the interface
> +could be something like this:
> +
> +Example @file{foo.h}:
> +
> address@hidden
> +#ifndef FOO_H
> +#define FOO_H
> +
> +int one (void);
> +int two (void);
> +extern int three;
> +
> +#endif /* FOO_H */
> address@hidden example
> +
> +And the implementation could be something like this:

@noindent here (before "And" on a line by itself)?  I'm not sure.

> +Example @file{foo.c}:
> +
> address@hidden
> +#include "foo.h"
> +
> +int one (void)
> address@hidden
> +  return 1;
> address@hidden
> +
> +int two (void)
> address@hidden
> +  return three - one ();
> address@hidden
> +
> +int three = 3;
> address@hidden example
> +
> +When using contemporary GNU tools to create the Windows DLL, the above
> +code will work there too, thanks to its auto-import/auto-export
> +features.  But that is not the case when using older GNU tools or perhaps
> +more interesting when using proprietary tools.  In those cases the code

interestingly?

> +will need additional decorations on the interface symbols with
> address@hidden(dllimport)} and @code{__declspec(dllexport)} depending
> +on if the library is built or if it's consumed and how it's built and

s/on if/on whether/; s/or if/or/  ?

> +consumed. However, it should be noted that it would have worked also

s/\. /& /

> +with Microsoft tools, if only the variable three hadn't been there, due

@code{three}

> +to the fact the Microsoft tools will automatically import functions (but
> +sadly not variables) and Libtool will automatically export non-static
> +symbols as described next.
> +
> +With Microsoft tools, Libtool will dig through the object files that
> +make up the library, looking for non-static symbols to automatically
> +export.  I.e., Libtool with Microsoft tools is trying to mimic the auto-
> +export feature of the contemporary GNU tools.  It should be noted that
> +the GNU auto-export feature is turned off when an explicit
> address@hidden(dllexport)} is seen.  The GNU tools do this to not make
> +more symbols visible for projects that have already taken the trouble to

present tense here?

> +decorate symbols.  There is no similar way to limit which symbols are
> +visible in the code when Libtool is using Microsoft tools.  In order to
> +limit symbol visibility in that case you need to use one of the options
> address@hidden or @option{-export-symbols-regex}.
> +
> +No matching help with auto-import is provided by Libtool, which is why
> +variables must be decorated to import them from a DLL for everything but
> +contemporary GNU tools.  As stated above, functions are automatically
> +imported by both contemporary GNU tools and Microsoft tools, but for
> +other proprietary tools the auto-import status of functions is unknown.
> +
> +When the objects that form the library are built, there are generally
> +two copies built for each object.  One copy is used when linking the DLL
> +and one copy is used for the static library.  On Windows systems, a pair
> +of defines are commonly used to discriminate how the interface symbols
> +should be decorated.  The first define is @samp{-DDLL_EXPORT} which is
> +automatically provided by Libtool when Libtool builds the copy of the

The second Libtool should most likely be @command{libtool} instead, as
you're pretty clearly speaking about the command and not behavior of the
whole package.  I think.

> +object that is destined for the DLL.  The second define is
> address@hidden (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 @code{--enable-auto-import} option for
> +some corner cases when it does not.

This should have a cross reference to just that documentation.

> +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 always present when the DLL is

s/always present/unavoidable/  ?

> +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 (@samp{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 @samp{-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 @file{foo.h}:
> +
> address@hidden
> +#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 */
> address@hidden example
> +
> +When the targets are limited to contemporary GNU tools and Microsoft
> +tools, the above can be simplified to the following:
> +
> +Simplified @file{foo.h}:
> +
> address@hidden
> +#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 */
> address@hidden example
> +
> +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 address@hidden
> +(@url{http://alain.frisch.fr/flexdll.html}) and address@hidden
> +(@url{http://edll.sourceforge.net/}).

Please write as:
   Examples are
   @uref{http://alain.frisch.fr/@/flexdll.html, FlexDLL} and
   @uref{http://edll.sourceforge.net/, edll}.

makeinfo should get the line breaking right by itself IMVHO.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]