Paul Sokolovsky wrote:
> 
> Hello Charles,
> 
> Charles S. Wilson <[EMAIL PROTECTED]> wrote:
> 
> CSW> I don't believe the following behavior is possible in the current
> CSW> libtool. However, if it is, please correct me.
> 
> CSW> In the upcoming libtool (1.4?) it would be nice on cygwin/windows-ish
> CSW> platforms, if the libfoo.la file could instruct libtool that it may need
> CSW> different -Ddefines when compiling an object file that is to be linked
> CSW> to a static lib or to a dynamic lib (dll).
> 
> CSW> gcc -c -DZLIB_STATIC -o my-file.o myfile.c
> CSW> gcc -static -o my-file.exe my-file.o -L<path> -lz
> 
> CSW> gcc -c -o my-file.o myfile.c
> CSW> gcc -o my-file.exe my-file.o -L<path> -lz
> 
> This behaviour impossible simply because libtool is not used for
> compiling client objects, only when compiling library objects, and
> linking - both clients and libs. 

Perhaps I'm confused, but I know that I've seen 'libtool --mode=compile
....' before.  And using libtool 'fully' requires that both the library
package and the client package are 'libtoolized', right?  (So that when
building the library, libfoo.la is created, and so that when linking the
client package, libfoo.la is the link target.)

There's no intrinsic reason why the client package couldn't also use
libtool to compile it's objects -- it just isn't done that way now. 
(You prove this yourself by setting CC='libtool gcc')  I'm *not* asking
that the libtool developers change the libtoolization process and
*force* client packages to use 'libtool --mode=compile' for client .o's
-- just that they make it possible to do so, and that when doing so that
the additional, necessary -Ddefine flags (if any) are retrieved from the
.la. 

Note: I would just go ahead, dig into the libtool code, and supply
patches myself to do this.  However, (1) I don't really understand how
it all works, and (2) Gary Vaughan has already expressed interest in
investigating, prior to the libtool-1.4 release, the necessary changes
in libtool for 'good' cygwin behavior.

> As you understand, it's probably
> far-fetched to expect that libtool interface will be changed because
> there's such a platform with such a stupid requirement.

Adding additional 'functions' to the libfoo.la format/libtool script is
not an interface *change* -- just an interface *addition*.  To draw an
analogy to the grand scheme of libtool library versioning, the interface
version number of the .la format remains compatible -- so no harm is
done.

Also, isn't the .la format different for distinct platforms, anyway?  If
so, then cygwin's .la format can have a few extra fields in it without
disrupting the other platforms.  If not, then my interface-compatibility
arguement above still holds.

> It is however,
> can be trivially and more or less seamlessly worked around *on that
> specific platform*, I use CC="libtool gcc" for that. But that
> workaround is only one in a long sequence of workarounds which will be
> required to support something more or less similar to features libtool
> offers on any other platform, workarounds which will be required if
> keeping up with stipulations prescribed by microsoft. But it's better to
> strike the root of problems - get rid of necessity for __declspec.

This can't be done without replacing the windows "dynamic loader" and
abandoning dll's on cygwin+windows.  Now, while that may not be such a
bad idea, it's certainly a huge job.  I'm asking for a minor (I think),
backwards-compatible change in the .la format and libtool's handling of
same, so that we can inch *closer* to normal unixish behavior on
cygwin+windows.  We won't get all the way there, but closer is good, no?

I'll quote DJ's explanation of the necessity for __declspec below.

For those on the libtool list, the -Ddefines that I'm talking about work
as follows (using the zlib package as an example): When building library
objects for inclusion in the dll, -DZLIB_DLL is used. When building
library objects for inclusion in the static library, or when building
client objects that will be linked to the static lib, -DZLIB_STATIC is
used.  The default procedure, in which client objects that will be
linked to the dll are built, no special defines are necessary.  In these
three cases, symbols in the header files are defined thus:

-DZLIB_DLL (building dll)
  #define ZEXPORT __declspec(dllexport)
  #define ZEXPORTVA __declspec(dllexport)
  #define ZEXPORTVAR __declspec(dllexport)

-DZLIB_STATIC (building static lib or building client .o for static
link)
  #define ZEXPORT
  #define ZEXPORTVA
  #define ZEXPORTVAR

(no define) (building client .o for dynamic link)
  #define ZEXPORT __declspec(dllimport)
  #define ZEXPORTVA __declspec(dllimport)
  #define ZEXPORTVAR __declspec(dllimport)

functions in the zlib package are declared like so:
  ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
  ZEXTERN int ZEXPORTVA   gzprintf OF((gzFile file, const char *format,
...));
(libz makes a distinction between 'normal' functions and variable-arg
functions; IMO not necessary, but...)

exported data in the zlib package (would be) declared like so:
  ZEXTERN int ZEXPORTVAR exported_variable;
(libz is actually a poor choice for this example, because there ARE no
exported data items. Oh well -- other libs export data; we'll pretend
zlib does, too)

As it happens (and DJ explains this below) it isn't really necessary to
jump through all these ZEXPORT hoops for functions, because the windows
"dynamic loader" can do the indirection and address fixups for functions
exported by a dll, without any special effort when a client object is
compiled.

However, these steps are abso-fraggin-lutely required for exported DATA
-- the windows "dynamic loader" can't do the fixups without help from
the compiler when the client .o is compiled.  So, you need special
__declspec -Ddefines to indicate: "I'm building a DLL" "I'm linking to a
DLL" "I'm building/linking to a static lib" when there is exported DATA
involved.

We made a design decision on the cygwin platform that "ported" software
would assume "I'm linking to a DLL" as default, and would use special
-Ddefines to "switch on" the other __declspec definitions.  (Okay, *I*
made that design decision but got very few (no?) objections from the
cygwin-apps list during the month or more that I was soliciting
comments)

Anyway, here's DJ's explanation about exported data items in a dll:

DJ Delorie wrote:
> Exported data needs to be treated specially by the application; the
> compiler must construct the program to access the data indirectly.
> This is different from functions, which can be indirected through the
> import library.  The linker cannot adjust the program to fix such
> data references if the compiler doesn't.
> 
> That being said, any tool which automatically exports data in a dll
> without adjusting the program that uses the dll (normally by editing
> the headers to explicitly mark such data items as being imported)
> creates a situation where the user could create a program which links
> successfully but mysteriously dies or produces inappropriate results.

That is, unless you rewrite the windows "dynamic loader", you can't get
rid of the __declspec requirement for exported/imported DATA items and
expect programs to work consistently and correctly.  There has been some
discussion about creating an entirely new dynamic library system for
cygwin that does not depend on Microsoft's braindead dll format.  If
such a herculean task were completed, then libtool on cygwin could act
just like libtool on other unix.  However, that task is so big that if
begun today, it still would not be complete for quite some time.

It seems to me that it is better to politely *ask* the libtool
developers (Gary?) to add a minor interface *extension* which remains
backward compatible so that libtool can work on cygwin, as cygwin is
now, rather than dreaming about replacing the windows "dynamic loader"
sometime in the future.  It also seems to me that now is the time to
mention it, since the great 1.3.x --> 1.4 libtool rewrite(?) is
happening now...

DJ Delorie further wrote: 
> By making the dll writer deal with marking exported data, we increase
> the chances that they'll fix the headers also, which would result in
> more working programs and less subtle failures (i.e. less FAQs and
> better overall confidence in the tools).
> 
> Even if the tool automatically exports *only* the _imp_ variant, to
> avoid the subtle link problems, the dll developer *still* needs to
> deal with each and every exported data item in the headers.  This is
> the hardest part of dealing with data imports, and any tool that falls
> short of solving this problem is not a complete tool.  I'm not against
> the idea of a partial tool, but I foresee many "why don't you finish
> this" type questions, and added partial functionality which creates
> user confusion is bad.

My translation: since we can't fix Microsoft's loader for them, let's at
least make it harder for people to shoot themselves in the foot (or
head).  No matter how hard we try, cygwin+windows != unix although it is
getting closer.

I grant that the changes I am mentioning here for libtool do NOT make
dll-izing a given library automatic.  You still must add the appropriate
__declspec() stuff in the headers (and switch definitions based on some
-DXXX_STATIC / -DXXX_DLL / (n/a)  set of flags).

Most of DJ's comments in the above two paragraphs are arguing the
necessity for special header hacks just as I've mentioned. DJ's context
is an automatic, type-and-go dll-izing tool.  I'm not talking about
that. All I'm talking about is this: when a package (such as zlib) has
*already* had the appropriate header-hacks, so that building a dll is
relatively streamlined -- can libtool handle it?

Can libtool be made to understand the necessity for -DZLIB_STATIC |
-DZLIB_DLL | (n/a) when building/linking statically | building the dll |
linking to the dll ?

DJ Delorie also further wrote:
> However, any patches [to binutils/ld/gcc] that *prevent* data items from 
>inadvertently
> being exported as functions would be welcome.

--Chuck

Reply via email to