[Top][All Lists]

[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: Wed, 13 Oct 2010 20:50:56 +0200
User-agent: Mutt/1.5.20 (2010-08-04)

Hi Peter,

* Peter Rosin wrote on Wed, Oct 13, 2010 at 08:19:27PM CEST:
> Can you spot any errors?

See below.  I've only checked for things obvious to me; I hope somebody
else verifies the w32 semantics and details.  ;-)

Thanks for writing this!

> (I have not actually tested the code samples. Yet)

Thanks in advance!  :-)

> 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

Two spaces after period.

> and using Microsoft tools.
> A typical library has a "hidden" implementation with an interface
> described in a header file. On just about every system, the interface
> could be something like this:
> Example foo.h:
> #ifndef FOO_H
> #define FOO_H
> int one (void);
> int two (void);
> extern int three;
> #endif /* FOO_H */
> And the implementation could be something like this:
> Example foo.c:
> #include "foo.h"
> int one (void)
> {
>   return 1;
> }
> int two (void)
> {
>   return 2;
> }
> int three = 3;

Isn't this less-than fully general, in the sense that having in addition
references to one and three from within two would possibly be more
complex to handle?

> 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
> will need additional decorations on the interface symbols with
> __declspec(dllimport) and __declspec(dllexport) depending on if the
> library is built or if it's consumed and how it's built and consumed.
> Concentrating on how Libtool is using Microsoft tools, Libtool will dig

How about simplifying this to
 With Microsoft tools, Libtool will dig ...

> through the object files making up the library looking for non-static

that make up the

> 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 in turned off when

s/ in / is /

> an explicit __declspec(dllexport) is seen. The GNU tools is doing this

s/is doing/do/  or  s/is/are/

> to not make more symbols visible for projects that have already taken
> the trouble to decorate all symbols. There is no similar way to limit

s/all// ?  (because how can you know that it did do so for all symbols,
when parts of the project may come from third parties?)

> 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 -export-symbols or -export-symbols-regex options.
> No matching help with auto-import is provided by Libtool for neither
> proprietary tools nor older GNU tools, so symbols *must* be decorated in
> order to import them from a DLL for everything but contemporary GNU
> tools on Windows.

But can we not assume that older GNU tools are irrelevant?  What would
keep people from updating them?

> 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, the
> copy used when creating the DLL is compiled with the flag -DDLL_EXPORT.

> It is common practice to also add a flag that is only present when the
> library is built, but that will not be present when it is consumed, such
> as -DBUILDING_LIBFOO. These defines are then used to discriminate how
> the interface symbols should be decorated.

This seems to be a bit reversed.  From a narrative standpoint, the
"common practice" only appears out of necessity, and the necessity has
not been explained yet.  Right?

> 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 saves the day.

because auto-import does what exactly?
(pointer to auto-import documentation from binutils?)

> With
> Microsoft tools you typically get away with always compiling the code as
> if it is going to be linked with a DLL. There are cases when this does
> not work, such as when only variables and no functions are imported from
> the 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 consumed, but it is not needed when
> consuming the static library.

This paragraph is fairly vague.  I understand if you don't want to tell
all the gory details about this, but in that case maybe a pointer to
more detailed documentation would be good here.

> 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 needs to be told what is intended.
> Or, to be exact, the author are not aware of any generic way. One

s/are/is/  This sounds a bit awkward still.

> assumption that has been used is that if a DLL is being built

that is commonly used?

> (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 _WIN32_WCE) && !defined __GNUC__
> #  ifdef DLL_EXPORT
> #   define LIBFOO_SCOPE extern __declspec (dllexport)
> #  endif
> # elif defined _MSC_VER || defined DLL_EXPORT
> #  define LIBFOO_SCOPE extern __declspec (dllimport)
> # endif
> #endif
> #ifndef LIBFOO_SCOPE
> # define LIBFOO_SCOPE extern
> #endif
> LIBFOO_SCOPE int one (void);
> LIBFOO_SCOPE int two (void);
> LIBFOO_SCOPE int three;
> #endif /* FOO_H */
> 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.



reply via email to

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