This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: binutils 20021107-2


Robert Collins wrote:


But, I think it's overkill to define "system libs that should not be re-exported" as "anything in /usr/lib" or something similarly broad.

Why? *anything* in /usr/lib is able to be linked to from multiple
packages. If one package creates a dll from there, then we will get this
problem. We're currently *manually* excluding *how many* libs? fortran.
gcc. stdc++. cygwin. And thats from memory. Do we want to hack ld when a
test g++-3.3 is released? IMO No.

No need. If we don't include the trailing '.' in the basename exclusion list, the same test can match
libtstdc++.a
libstdc++-2.a
libstdc++-3.3.a
or whatever. Chris just committed a patch to binutils CVS that does this generalization.


I think that nothing specific to gcc should be handled by ld. If gcc
knows about file foo, be that mingw specific, or c++ specific, it should
tell ld to do the right thing. This centralises the knowledge about the
exceptions.

Ideally, sure -- but that'll require a LOT of info to be passed (see below). But the fact is, ld already incorporates LOTS of knowledge about the way gcc does things -- and not just on cygwin/win32. binutils is tightly tied to gcc (and vice versa), like it or not.


On the other hand, we're really arguing about a problem that hasn't bit anyone yet. By excluding the main (gcc) static runtime libs from re-export, and the main (platform) static runtime libs like libmingw32 libmingwex from re-export -- we pretty much cover all the important bases.

True. My suspicion though is that as folk find .dll's easier to build,
with the libtool dll support hitting mainstream as of(?1.4?) it will be
more common to link against something. Let me give you another contrived
example:

I create a static lib foo (say readline for arguments sake). It gets
installed into /usr/local/lib.

Someone else makes a library bar depending on foo. This library is a
.dll. It gets installed into /usr/local/lib.

Aha! But that can't happen given the recent changes in libtool. If any dependency is static, then libtool will refuse to create a DLL (unless: my changes exempt the platform and compiler libs from this check. But, I don't hardcode them in libtool; libtool computes the stdlib names from gcc and ld output)

Now, if you're building a DLL "by hand" then sure, problems can happen. But as you say, DLL-making will only become widespread "with the libtool dll support hitting mainstream". 1.4.x had a limited version, which still required lots of sourcecode modification and __declspec magic. 1.5.x will use auto-import, and life will become VERY easy. That's mainstream. 1.4.x was an attempt, but turned out to be too difficult in practice.


Every app that links against both foo and bar (and if bar is a libtool
library, it will suck in foo for us) will get duplicate symbols.

Nope. See above. This is why I agree, in principle, with the recent changes in libtool that made things suck briefly. It was a lot of work to "fix" -- but the general idea "don't build sharedlibs that depend on static libs" is a good one. And is still in place, even in my patched versions of recent libtool.

Anything else is obviously a corner case, since it hasn't bit anyone yet -- and the fix is for that person to specifically exclude the static lib that "bit" them by using --exclude-libs.

That is *a* fix. Why doesn't it bite folk on linux or BSD? Why should it
bite anyone here when *we can make ld do the right thing*.

It *did* bite linux/BSD folks -- but since ELF has provisions for symbol overriding, it didn't really have too much of an effect. We don't have those provisions; duplicate symbols are a major problem in pei-386.

That's why the recent changes to libtool prohibit buiding sharedlibs that depend on static libs -- to avoid these problems (even the minor ones on linux/BSD).

In my libtool changes, I'm only arguing for an *exception* to that algorithm when the static libs in question are gcc-provided or platform-provided ones, that already have "don't re-export me" provisions in ld. [but I'm not hardcoding that knowledge; it's computed on-the-fly from gcc/ld output] But that's a libtool discussion.

In binutils, we already have a "don't re-export me" list. I think that the following heuristic is reasonable for keeping that list short:

1) libraries provided by the gcc compiler suite
2) win32 (cygwin, mingw, pw32) "platform" libraries that are commonly available only as static libs. [remember, this code is in pe-dll.c and only applies to win32ish platforms]

We already refuse to re-export symbols imported from DLLs. So, we only need to worry about "standard" libs that are available only as static libs.

Right now, that's a short list: the gcc libs, and libmingw32 + libmingwex. The end. Dropping the final '.' in the matchstring, and we can exclude all versioned instances of the gcc libs, without making the list too long.


We only want to export static archive symbols when a) it's a convenience library, b) we are creating a forwarding library for the archive.

or when --whole-archive libfoo.a --no-whole-archive is used. Or when libtool can't fit all of the objects on a single commandline, and has to build separate archives. [these are not treated as convenience libs, becuase clibs get incorporated into DLLs by *unpacking them* and explicitly listing the component objects on the link command -- which doesn't help the linkcmd length :-) ]

Refusing to export symbols from "static" archives in general on cygwin, will break established idioms (not counting libtool). As I explained earlier, libtool has already decided to prevent this action in general.


In a) the library won't be in /usr/lib unless you are building from a
subdir of that (unlikely!).

true


In b) the library *may* be in /usr/lib, so we can allow a --include-libs
flag to override the heuristic (and I think we already have one, no?)

Urgh. Not another flag. (unless your "we already have one" reference is to --whole-archive).


The problem here, is that because of our packaging of gcc-2, we're missing the names of the (gcc) static runtime libs for that "package". Plus, libmingwex is another (platform) static runtime lib that we're missing -- but it was only recently added to the mingw "platform".

The problem is that dll's are non intuitive, and our automagic support
is incomplete :}. There's a refactoring smell, uhmm, 'Shotgun Surgery'.
When we change the names of common system libraries, we have to change
ld as well. That's plain wrong.

Yes, it would be -- if we were changing the names. Do you really think that libgcc is going to change its name anytime soon? We shouldn't have included the trailing '.' in the first place; removing it solves all of your versioned runtimelibs worries at once.

It is kinda kludgy that everytime a new compiler frontend is added, we'd need to add that frontend's runtime lib to the exclude list. But we've added exactly ONE new frontend in five years. gcj. Sue me.

[BTW, each front end needs work to support __declspec() attributes and autoimport before this really becomes an issue. Right now, g77 doesn't support exporting DATA items from DLLs at all; only functional interfaces are allowed. This is because the g77 frontend won't allow us to decorate common block variables (__declspec(); old style). And that's a prerequisite for working auto-import/auto-export support. So libtool-on-cygwin doesn't even pretend to support DLLs in fortran. And there's no provision for gcj at all. One thing at a time. And the gcc frontends need work first]

And binutils IS tightly linked to gcc. If it needs to know the names of the gcc-provided libs, thats okay with me. In an ideal world, our gcc spec file would include
--exclude-lib=libstdc++
every time it mentions -lstdc++. And there would be a similar ld command called "--exclude-object" so that every time gcc's spec file added
crt0.o
it would also say
--exclude-object=crt0.o
And ld wouldn't need a list of "internal DLL layout symbols" like
{ "_head_", 6 },
{ "_fmode", 6 },
{ "_impure_ptr", 11 },
{ "cygwin_attach_dll", 17 },
{ "cygwin_premain0", 15 },
{ "cygwin_premain1", 15 },
{ "cygwin_premain2", 15 },
{ "cygwin_premain3", 15 },
{ "environ", 7 },
because the gcc spec file would say --exclude-symbol=... every damn time you build a DLL.

Where do you stop? As a practical matter, ld can't be purely data driven; it needs to KNOW some things about DLLs. And the platforms where DLLs are used, like cygwin and mingw. And it needs to know about the ONLY compiler suite on those platforms: gcc.

I really don't think the current "division of knowledge" is that bad.

I think that the revised patch is fine, along the existing approach, but
the existing approach is much less than optimal.

There are certainly areas where improvements can be made -- but your idea of optimal is suboptimal, IMO. :-) Your desire seems to be similar to that of setup.exe: purely data driven. I think that's a great idea for setup -- but I don't think it's a good path for ld. Right now ld handles some things, and gcc handles others -- and
1) some knowledge is shared (e.g. is maintained in the codebase, and must be coordinated to some extent)
2) other knowledge is passed on the command line (gcc's spec file)

The stuff in 1) doesn't change often (time constant == years? The last change to this part of the code was August 2001). I think the division of knowledge is about right, subject to minor tweaking.

--Chuck


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]