On Mar 6, 2002, Tom Tromey <[EMAIL PROTECTED]> wrote: >>>>>> "Alexandre" == Alexandre Oliva <[EMAIL PROTECTED]> writes: Alexandre> Actually, I was thinking of libgcj.la being linked with Alexandre> $(THREADLIBS) first, which would solve the problem just the Alexandre> same.
> We already do that: > libgcj_la_LDFLAGS = -rpath $(toolexeclibdir) $(THREADLIBS) $(LIBLTDL) \ > $(GCLIBS) $(ZLIBS) \ > So something else must be required. Ok, I see the problem now. It's indeed a bug in libtool. Basically, the problem is that libtool sometimes decides it can drop duplicate -l flags from the command line, when it thinks it is safe to do so. Currently, the rules is that, if a library does not explicitly appear more than once in the dependency list of a library, libtool assumes there's no problem if it simply discards any previous occurrences of such a library. On the other hand, if a library appears more than once in a dependency list (say, libjava is linked with -lgcc_s -lc -lgcc_s), libtool considers the duplicate library as a special library that strongly depends on ordering, and does not move it. The problem is that -lpthread ends up being removed from before the first copy of -lgcc_s, because it is not explicitly duplicated and thus it's taken as a movable library, while the first copy of -lgcc_s remains, as it is taken as unmovable. I don't see an easy way to fix this problem in libtool. It would require every unmovable library to establish a barrier such that no libraries that appear before it can be dropped. Since every C++ library has -lgcc_s -lc -lgcc_s in its dependency list, this would defeat the whole purpose of the duplicate-removal of dependencies, that was an absolute must for large packages with hundreds of libraries, such as KDE. Without such an optimization, building KDE would easily overflow the command line size on most, if not all OSs (except any one that does not impose fixed limits on command line sizes), due to exponential explosion of `-lm -lgcc -lc -lgcc' in the command line. Ideally, libtool should try to tell whether a library is dynamic or static in order to decide whether to eliminate all but the first or all but the last duplicates of -l flags (except for static libraries marked as special), but I'm not even sure this would be correct. Anyway, there are several ways to alleviate the impact of this problem in libjava and GCC. The simplest solution I could come up with was to drop from the link command of executables any libraries that were already in the dependency list of libgcj, so they'd be automatically brought in. This was enough to fix the problem at hand: now gij is linked with -lpthread before -lgcc_s, since there's no duplicate of -lpthread after the first implicit occurrence of -lgcc_s that was brought in from libgcj.la itself. The patch that fixes this problem is attached. Another possibility that occurred to me, that would further alleviate the problem of duplicate shared libraries, would be to get GCC to no longer issue the `-lgcc_s -lc -lgcc_s' sequence, but instead, to use just `-lgcc_s -lc'. I believe this would be a perfectly safe thing to do in the context of a shared -lgcc_s, no? We'd might still have to add duplicates for -lgcc and -lgcc_eh, so it might end up not being of much help. It's probably worth a shot, though. Any opposition to my changing the GCC specs to that effect? Yet another solution would be to get libtool to recognize libraries and object files implicitly linked in especially. It already does something to that effect, but it still considers duplicate libraries at such points as special. Sometimes I think adding the code to peek into the flags implicitly passed by g++ to the linker was a mistake, but then I think of how nice it is to be able to link with a libtool (possibly static) library using `libtool gcc', even if the library itself contains C++ code and has to be linked with -lstdc++, with the certainty that libtool will add the -lstdc++ dependency by itself since it learned about such dependency when looking at the arguments g++ passed to the linker when creating the original library. And then, sometimes libtool just can't use (old versions of) g++ to link shared libraries, because they're broken, and then it's essential for it to figure out which flags g++ would pass to the linker, drop those that would break (such as static libstdc++ that can't be linked into a shared library) and go with the rest of the args running the linker directly. Other libtoolers, any further suggestions as to how to fix this real libtool bug? Anyway, here's the patch for libjava. I'm checking it in mainline and in the 3.1 branch. Bootstrapped on athlon-pc-linux-gnu with --enable-threads, and verified by visual inspection that the link command line of gij and other libjava executables did contain -lpthread before -lgcc_s -lc -lgcc_s.
Index: libjava/ChangeLog from Alexandre Oliva <[EMAIL PROTECTED]> * Makefile.am (jv_convert_LDADD): Don't list libraries that are already implicitly brought in from libgcj.la. (gij_LDADD, rmic_LDADD, rmiregistry_LDADD): Likewise. * Makefile.in: Rebuilt. Index: libjava/Makefile.am =================================================================== RCS file: /cvs/gcc/egcs/libjava/Makefile.am,v retrieving revision 1.205 diff -u -p -r1.205 Makefile.am --- libjava/Makefile.am 2002/03/06 18:54:35 1.205 +++ libjava/Makefile.am 2002/03/15 22:14:58 @@ -429,7 +429,7 @@ jv_convert_LINK = $(GCJLINK) ## system libraries we need (via the specs file). ## We need the -L so that gcj can find libgcj with `-lgcj'. ## FIXME: should be _libs on some systems. -jv_convert_LDADD = libgcj.la $(GCLIBS) $(THREADLIBS) $(ZLIBS) -L$(here)/.libs +jv_convert_LDADD = libgcj.la -L$(here)/.libs ## Depend on the spec file to make sure it is up to date before ## linking this program. jv_convert_DEPENDENCIES = $(convert_source_files:.java=.lo) \ @@ -446,7 +446,7 @@ gij_LINK = $(GCJLINK) ## system libraries we need (via the specs file). ## We need the -L so that gcj can find libgcj with `-lgcj'. ## FIXME: should be _libs on some systems. -gij_LDADD = libgcj.la $(GCLIBS) $(THREADLIBS) $(ZLIBS) -L$(here)/.libs +gij_LDADD = libgcj.la -L$(here)/.libs ## Depend on the spec file to make sure it is up to date before ## linking this program. gij_DEPENDENCIES = $(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec @@ -462,7 +462,7 @@ rmic_LINK = $(GCJLINK) ## system libraries we need (via the specs file). ## We need the -L so that gcj can find libgcj with `-lgcj'. ## FIXME: should be _libs on some systems. -rmic_LDADD = libgcj.la $(GCLIBS) $(THREADLIBS) $(ZLIBS) -L$(here)/.libs +rmic_LDADD = libgcj.la -L$(here)/.libs ## Depend on the spec file to make sure it is up to date before ## linking this program. rmic_DEPENDENCIES = $(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec @@ -478,7 +478,7 @@ rmiregistry_LINK = $(GCJLINK) ## system libraries we need (via the specs file). ## We need the -L so that gcj can find libgcj with `-lgcj'. ## FIXME: should be _libs on some systems. -rmiregistry_LDADD = libgcj.la $(GCLIBS) $(THREADLIBS) $(ZLIBS) -L$(here)/.libs +rmiregistry_LDADD = libgcj.la -L$(here)/.libs ## Depend on the spec file to make sure it is up to date before ## linking this program. rmiregistry_DEPENDENCIES = $(GCDEPS) $(THREADDEPS) $(ZDEPS) libgcj.la libgcj.spec
-- Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/ Red Hat GCC Developer aoliva@{cygnus.com, redhat.com} CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org} Free Software Evangelist Professional serial bug killer