This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC 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: printing exceptions?


On Mar  6, 2002, Tom Tromey <tromey@redhat.com> wrote:

>>>>>> "Alexandre" == Alexandre Oliva <aoliva@redhat.com> 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  <aoliva@redhat.com>

	* 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

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