From: Godmar Back (gback@cs.utah.edu)
Date: Sun Jan 17 1999 - 23:05:13 EST
[Note: I cc'd the libtool crew because I believe that this mail is of interest
to all of you. As you may or may not know, Alexandre is trying to libtoolize
Kaffe, and we are having serious problems. This mail discusses the problems
introduced by libtool's tendency to create funny and bogus link lines that
don't create executables on some systems. However, it is more serious than
that.]
Alexandre,
here's my opinion on how to make libtool a truely useful tool with
regard to linking multiple libraries. A lot of it comes from my
experience with linking the OSKit, which is a set of libraries to build OSes.
What I am talking about are hours wasted trying to arrange link lines,
to resolve multiply defined symbols conflicts, and hours wasted trying to
debug failures caused by the inclusion of a different function than intended.
First, I consider it fundamentally wrong for a tool to encourage linking
mistakes by adding libraries to the link line multiple times without being
told to do so --- like libtool apparently does. I apologize if I am
mistaken on this point.
Lemma 1:
A link line should contain every library exactly once.
Period. Big Period.
Libtool should define anything else to be a *bug*, and libtool --- if
it truely wants to be a useful tool, should
a) flag that situation loud and clearly.
b) not take *any* corrective action *unless* explicitly told by the user.
Some libraries are *broken*. Clearly, libtool should assist the user
in handling such broken libraries, but it should not assist the user
in creating broken libraries. I consider three types of bugs, I'm sure
there are more:
a) The first bug is that libraries are interdependent. Library one defines
a symbol that library two defines, and vice versa. The usual work-around
here is to specify: -llib1 -llib2 -llib1 -llib2.
This, however, is highly fragile and dangerous. Libtool should not
encourage such deviant behavior.
If a user wants to be a smart ass and insists, he should be required
to *explicitly* tell libtool which libraries should be listed twice.
The -l\( -l\) switches in GNU ld should never have been invented.
(An social proof of that fact is that I heard about it from
the original GNU make author Roland McGrath first.)
b) The second bug is the use of so-called library overriding. The classic
example is the famous -lXm -lXt -lX11 line, where libXm.a redefines
and overrides symbols in libXt.a. In this case, it was done because
libXt is buggy from Motif's view point.
If that is the case, then libtool is again powerless. The user and
only the user will know in what order the libraries have to appear,
and libtool has to believe him. Of course, if there are well-known
cases of where library overriding must be used --- like the Motif
case --- then libtool could be taught about it, on a case-by-case basis.
The -lgcc hack proposed for FreeBSD's lrem bug in kaffe may be another
example, although a rather weak one.
c) The third mistake is caused by people who have tried (and failed) to use
library overriding as a feature (namely, us stupid OSKit folks.)
In the OSKit, for instance, users are encouraged to provide their
own implementation of certain functions which will then be used by
the libraries of the Kit.
The classic mistakes that are bound to happen are that the overridden
symbol itself is part of a library, but is not referenced until the
library whose symbol was to be overwritten is read by the linker.
For example, suppose lib1.a defines a() and b(), and lib2.a attempts
to override a(), but not b(), then linking with "-l2 -l1" will
not pull in lib1's a(), but lib2's a().
Libtool should help to detect such bugs. In fact, check out
~gback/supertool/st.l for an example of how. This lex script (I'm sure
you could use perl or whatever, but lex&dbm is pretty fast) parses
a GNU ld linker map and detects such situations. Easy enough.
Once detected, the user should either
a) fix his mistake.
b) or, if he uses somebody else's library, add the output of st to his
.o files. For the example I just gave, st would produce this:
/* was taken from ./lib1.a instead of ./lib2.a */
void a(void);
static void _1() { a(); }
I hope this is useful input. The reason I'm writing is that the use of
the word "transparent" in the following TODO entry in libtool/TODO made me
highly concerned:
* Inter-library dependencies should be fully tracked by libtool.
Reminded by Alexandre Oliva. This requires looking up installed
libtool libraries for transparent support.
I sincerely hope you won't go down that slippery slope. I've been there,
done that and I am now a fan of COM.
- Godmar
This archive was generated by hypermail 2b29 : Sat Sep 23 2000 - 19:57:44 EDT