Subject: Re: xforms and undefined reference to `fl_initialize'
To: Jeremy C. Reed <reed@reedmedia.net>
From: Frederick Bruckman <fb@enteract.com>
List: netbsd-help
Date: 02/04/2001 11:47:11
On Sat, 3 Feb 2001, Jeremy C. Reed wrote:

> Well, I figured out how why my xforms-based program wouldn't build with
> libforms.a.
>
> I had the command-line options in the wrong order. This works:
>
>  gcc -I/usr/X11R6/include/X11 -I/usr/X11R6/include test.c -o test
>  -L/usr/X11R6/lib -lforms -lXpm -lX11 -lm

I'm guessing that this resolves to something like

  gcc -I/usr/X11R6/include/X11 -I /usr/X11R6/include test.c -o
  /tmp/test.o
  gcc -o test /tmp/test.o -L/usr/X11R6/lib -lforms -lXpm -lX11 -lm

The second command in turn invokes ld with the same arguments. The
linker reads this from left to right -- fl_initialize is added to the
list of symbols to be resolved by successive objects, then it's
resolved by libforms.a. Unused symbols in static libraries (the GL* in
libforms.a) don't (usually) need to be resolved.

> This does not:
>
>  gcc -I/usr/X11R6/include/X11 -I/usr/X11R6/include -L/usr/X11R6/lib
>  -lforms -lXpm -lX11 -lm test.c -o test
>
> But this would work when the liforms.so exists (and using -lGL). Why does
> it matter on the order vs. lib*.so and lib*.a?

Some linkers will go backwards to search for unresolved symbols in
_shared_ _libraries_ (but it's a crap shoot). This allows you to have
unreslved symbols in two or more shared objects that each resolve in
the other. I've never seen that work with _static_ _libraries_. It's
easy to do with shared libraries even without the feature; you just
list some one or more of the libraries more than once.

The reason you need -lGL to link in the libforms.so case is that the
ELF spec requires it (I'm told). I said "usually" for the static case
because it "just works" now, but there's no guarantee it will continue
to do so on all platforms in the future...

Consider what happens when you call a wrapper function in libforms
that in turn calls a libGL function, but GL.so doesn't turn up in the
list of objects to link. The linker sees the unresolved GL...  symbol
in libforms.so, but there's absolutely no way for the linker to grok
the relationship between that and the specific function that calls it.
The choices are 1) alert the developer at link time 2) do nothing at
link time: when the user twiddles the knob in the program that calls
the wrapper, the program will dump core. If your linker does "2", and
that's what you want, enjoy, but know that world is moving towards "1".

Another thing. If libforms.so.* had been linked properly, on a recent
NetBSD system, it would have a run-time dependency on -lGL. You would
not need to put -lGL on the command line, but you would be alerted at
both link- and run-time if GL.so were missing.


Frederick